diff --git a/Makefile b/Makefile index 4777a30d..ea877edb 100644 --- a/Makefile +++ b/Makefile @@ -133,7 +133,7 @@ endif .PHONY : all debug release clean depend zip version force install uninstall -OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/divers.o $(OBJDIR)/special.o $(OBJDIR)/boutons.o $(OBJDIR)/palette.o $(OBJDIR)/aide.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/moteur.o $(OBJDIR)/files.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/clavier.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/texte.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o +OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/divers.o $(OBJDIR)/special.o $(OBJDIR)/boutons.o $(OBJDIR)/palette.o $(OBJDIR)/aide.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/moteur.o $(OBJDIR)/files.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/clavier.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/texte.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o CFGOBJ = $(OBJDIR)/gfxcfg.o $(OBJDIR)/SFont.o $(OBJDIR)/clavier.o $(OBJDIR)/io.o $(OBJDIR)/setup.o all : $(BIN) $(CFGBIN) diff --git a/Makefile.dep b/Makefile.dep index e2f24572..ee10b005 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -3,7 +3,8 @@ $(OBJDIR)/aide.o: aide.c const.h struct.h global.h loadsave.h divers.h graph.h \ moteur.h tables_aide.h aide.h sdlscreen.h texte.h clavier.h $(OBJDIR)/boutons.o: boutons.c const.h struct.h global.h loadsave.h divers.h \ graph.h moteur.h readline.h files.h init.h boutons.h operatio.h pages.h \ - erreurs.h readini.h saveini.h shade.h io.h aide.h texte.h sdlscreen.h + erreurs.h readini.h saveini.h shade.h io.h aide.h texte.h sdlscreen.h windows.h brush.h +$(OBJDIR)/brush.o: brush.c brush.h erreurs.h windows.h sdlscreen.h $(OBJDIR)/clavier.o: clavier.c global.h struct.h const.h loadsave.h $(OBJDIR)/divers.o: divers.c struct.h const.h sdlscreen.h global.h loadsave.h \ graph.h erreurs.h boutons.h moteur.h divers.h clavier.h @@ -13,16 +14,16 @@ $(OBJDIR)/gfxcfg.o: gfxcfg.c SFont.h struct.h const.h clavier.h io.h hotkeys.h \ setup.h $(OBJDIR)/graph.o: graph.c global.h struct.h const.h loadsave.h moteur.h boutons.h \ pages.h erreurs.h sdlscreen.h graph.h divers.h pxsimple.h pxtall.h \ - pxwide.h + pxwide.h windows.h $(OBJDIR)/init.o: init.c const.h struct.h global.h loadsave.h graph.h boutons.h \ palette.h aide.h operatio.h divers.h erreurs.h clavier.h io.h hotkeys.h \ - files.h setup.h + files.h setup.h windows.h $(OBJDIR)/io.o: io.c struct.h const.h io.h $(OBJDIR)/loadsave.o: loadsave.c const.h struct.h global.h loadsave.h graph.h \ divers.h pages.h op_c.h boutons.h erreurs.h io.h sdlscreen.h $(OBJDIR)/main.o: main.c const.h struct.h global.h loadsave.h graph.h divers.h \ init.h boutons.h moteur.h pages.h files.h sdlscreen.h erreurs.h \ - readini.h saveini.h io.h texte.h setup.h + readini.h saveini.h io.h texte.h setup.h windows.h brush.h $(OBJDIR)/moteur.o: moteur.c const.h struct.h global.h loadsave.h graph.h divers.h \ special.h boutons.h operatio.h shade.h erreurs.h sdlscreen.h $(OBJDIR)/op_c.o: op_c.c op_c.h struct.h const.h erreurs.h graph.h @@ -39,18 +40,19 @@ $(OBJDIR)/pxtall.o: pxtall.c global.h struct.h const.h loadsave.h sdlscreen.h \ divers.h pxsimple.h $(OBJDIR)/pxwide.o: pxwide.c global.h struct.h const.h loadsave.h sdlscreen.h \ divers.h -$(OBJDIR)/readini.o: readini.c const.h global.h struct.h loadsave.h graph.h +$(OBJDIR)/readini.o: readini.c const.h global.h struct.h loadsave.h graph.h divers.h $(OBJDIR)/readline.o: readline.c const.h struct.h global.h loadsave.h graph.h \ divers.h erreurs.h sdlscreen.h readline.h $(OBJDIR)/saveini.o: saveini.c const.h global.h struct.h loadsave.h readini.h io.h \ - erreurs.h graph.h + erreurs.h graph.h divers.h $(OBJDIR)/sdlscreen.o: sdlscreen.c global.h struct.h const.h loadsave.h sdlscreen.h \ erreurs.h graph.h $(OBJDIR)/setup.o: setup.c struct.h const.h io.h files.h $(OBJDIR)/shade.o: shade.c global.h struct.h const.h loadsave.h graph.h moteur.h \ - divers.h readline.h aide.h sdlscreen.h + divers.h readline.h aide.h sdlscreen.h windows.h $(OBJDIR)/special.o: special.c const.h struct.h global.h loadsave.h graph.h \ moteur.h $(OBJDIR)/texte.o: texte.c SFont.h struct.h const.h global.h loadsave.h sdlscreen.h \ io.h files.h $(OBJDIR)/version.o: version.c +$(OBJDIR)/windows.o: windows.c windows.h graph.h moteur.h divers.h struct.h sdlscreen.h diff --git a/boutons.c b/boutons.c index 02146c7d..d6844d7d 100644 --- a/boutons.c +++ b/boutons.c @@ -48,6 +48,8 @@ #include "aide.h" #include "texte.h" #include "sdlscreen.h" +#include "windows.h" +#include "brush.h" #ifdef __WATCOMC__ #include diff --git a/brush.c b/brush.c new file mode 100644 index 00000000..eeadbac3 --- /dev/null +++ b/brush.c @@ -0,0 +1,1764 @@ +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Franck Charlet + Copyright 2007-2008 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. + +******************************************************************************** + + Brush manipulation functions +*/ + +#include + +#include "global.h" +#include "graph.h" +#include "divers.h" +#include "erreurs.h" +#include "windows.h" +#include "sdlscreen.h" + +// Calcul de redimensionnement du pinceau pour éviter les débordements de +// l'écran et de l'image +void Calculer_dimensions_clipees(short * X,short * Y,short * Largeur,short * Hauteur) +{ + if ((*X)(Limite_Droite+1)) + { + (*Largeur)=(Limite_Droite-(*X))+1; + } + + if ((*Y)(Limite_Bas+1)) + { + (*Hauteur)=(Limite_Bas-(*Y))+1; + } +} + + // -- Calcul de redimensionnement du pinceau pour éviter les débordements + // de l'écran zoomé et de l'image -- + +void Calculer_dimensions_clipees_zoom(short * X,short * Y,short * Largeur,short * Hauteur) +{ + if ((*X)(Limite_Droite_Zoom+1)) + { + (*Largeur)=(Limite_Droite_Zoom-(*X))+1; + } + + if ((*Y)(Limite_Bas_Zoom+1)) + { + (*Hauteur)=(Limite_Bas_Zoom-(*Y))+1; + } +} + + + // -- Afficher le pinceau (de façon définitive ou non) -- + +void Afficher_pinceau(short X,short Y,byte Couleur,byte Preview) + // X,Y: position du centre du pinceau + // Couleur: couleur à appliquer au pinceau + // Preview: "Il ne faut l'afficher qu'à l'écran" +{ + short Debut_X; // Position X (dans l'image) à partir de laquelle on + // affiche la brosse/pinceau + short Debut_Y; // Position Y (dans l'image) à partir de laquelle on + // affiche la brosse/pinceau + short Largeur; // Largeur dans l'écran selon laquelle on affiche la + // brosse/pinceau + short Hauteur; // Hauteur dans l'écran selon laquelle on affiche la + // brosse/pinceau + short Debut_Compteur_X; // Position X (dans la brosse/pinceau) à partir + // de laquelle on affiche la brosse/pinceau + short Debut_Compteur_Y; // Position Y (dans la brosse/pinceau) à partir + // de laquelle on affiche la brosse/pinceau + short Pos_X; // Position X (dans l'image) en cours d'affichage + short Pos_Y; // Position Y (dans l'image) en cours d'affichage + short Compteur_X; // Position X (dans la brosse/pinceau) en cours + // d'affichage + short Compteur_Y; // Position Y (dans la brosse/pinceau) en cours + // d'affichage + short Fin_Compteur_X; // Position X ou s'arrête l'affichade de la + // brosse/pinceau + short Fin_Compteur_Y; // Position Y ou s'arrête l'affichade de la + // brosse/pinceau + byte Couleur_temporaire; // Couleur de la brosse en cours d'affichage + int Position; + byte * Temp; + + if (!(Preview && Mouse_K)) // Si bouton enfoncé & preview > pas de dessin + switch (Pinceau_Forme) + { + case FORME_PINCEAU_POINT : // !!! TOUJOURS EN PREVIEW !!! + if ( (Pinceau_X>=Limite_Gauche) + && (Pinceau_X<=Limite_Droite) + && (Pinceau_Y>=Limite_Haut) + && (Pinceau_Y<=Limite_Bas) ) + { + Pixel_Preview(Pinceau_X,Pinceau_Y,Couleur); + Mettre_Ecran_A_Jour(X,Y,1,1); + } + break; + + case FORME_PINCEAU_BROSSE_COULEUR : // Brosse en couleur + + Debut_X=X-Brosse_Decalage_X; + Debut_Y=Y-Brosse_Decalage_Y; + Largeur=Brosse_Largeur; + Hauteur=Brosse_Hauteur; + Calculer_dimensions_clipees(&Debut_X,&Debut_Y,&Largeur,&Hauteur); + if (Largeur<=0 || Hauteur<=0) + break; + Debut_Compteur_X=Debut_X-(X-Brosse_Decalage_X); + Debut_Compteur_Y=Debut_Y-(Y-Brosse_Decalage_Y); + Fin_Compteur_X=Debut_Compteur_X+Largeur; + Fin_Compteur_Y=Debut_Compteur_Y+Hauteur; + + if (Preview) + { + if ( (Largeur>0) && (Hauteur>0) ) + Display_brush_Color( + Debut_X-Principal_Decalage_X, + Debut_Y-Principal_Decalage_Y, + Debut_Compteur_X, + Debut_Compteur_Y, + Largeur, + Hauteur, + Back_color, + Brosse_Largeur + ); + + if (Loupe_Mode) + { + Calculer_dimensions_clipees_zoom(&Debut_X,&Debut_Y,&Largeur, + &Hauteur + ); + + Debut_Compteur_X=Debut_X-(X-Brosse_Decalage_X); + Debut_Compteur_Y=Debut_Y-(Y-Brosse_Decalage_Y); + + if ( (Largeur>0) && (Hauteur>0) ) + { + // Corrections dues au Zoom: + Debut_X=(Debut_X-Loupe_Decalage_X)*Loupe_Facteur; + Debut_Y=(Debut_Y-Loupe_Decalage_Y)*Loupe_Facteur; + Hauteur=Debut_Y+(Hauteur*Loupe_Facteur); + if (Hauteur>Menu_Ordonnee) + Hauteur=Menu_Ordonnee; + + Display_brush_Color_zoom(Principal_X_Zoom+Debut_X,Debut_Y, + Debut_Compteur_X,Debut_Compteur_Y, + Largeur,Hauteur,Back_color, + Brosse_Largeur, + Buffer_de_ligne_horizontale); + } + } + + Mettre_Ecran_A_Jour(X-Brosse_Decalage_X,Y-Brosse_Decalage_Y,Brosse_Largeur,Brosse_Hauteur); + + } + else + { + if ((Smear_Mode) && (Shade_Table==Shade_Table_gauche)) + { + if (Smear_Debut) + { + if ((Largeur>0) && (Hauteur>0)) + { + Copier_une_partie_d_image_dans_une_autre( + Principal_Ecran, Debut_X, Debut_Y, Largeur, Hauteur, + Principal_Largeur_image, Smear_Brosse, + Debut_Compteur_X, Debut_Compteur_Y, + Smear_Brosse_Largeur + ); + Mettre_Ecran_A_Jour(Debut_X,Debut_Y,Largeur,Hauteur); + } + Smear_Debut=0; + } + else + { + for (Pos_Y = Debut_Y, Compteur_Y = Debut_Compteur_Y; + Compteur_Y < Fin_Compteur_Y; + Pos_Y++, Compteur_Y++ + ) + for (Pos_X = Debut_X, Compteur_X = Debut_Compteur_X; + Compteur_X < Fin_Compteur_X; + Pos_X++, Compteur_X++ + ) + { + Couleur_temporaire = Lit_pixel_dans_ecran_courant( + Pos_X,Pos_Y + ); + Position = (Compteur_Y * Smear_Brosse_Largeur)+ Compteur_X; + if ( (Lit_pixel_dans_brosse(Compteur_X,Compteur_Y) != Back_color) + && (Compteur_Y=Smear_Min_Y) && (Compteur_X>=Smear_Min_X) ) + Afficher_pixel(Pos_X,Pos_Y,Smear_Brosse[Position]); + Smear_Brosse[Position]=Couleur_temporaire; + } + + Mettre_Ecran_A_Jour(Debut_X,Debut_Y,Largeur,Hauteur); + } + + Smear_Min_X=Debut_Compteur_X; + Smear_Min_Y=Debut_Compteur_Y; + Smear_Max_X=Fin_Compteur_X; + Smear_Max_Y=Fin_Compteur_Y; + } + else + { + if (Shade_Table==Shade_Table_gauche) + for (Pos_Y=Debut_Y,Compteur_Y=Debut_Compteur_Y;Compteur_Y0) && (Hauteur>0) ) + Display_brush_Mono(Debut_X-Principal_Decalage_X, + Debut_Y-Principal_Decalage_Y, + Debut_Compteur_X,Debut_Compteur_Y, + Largeur,Hauteur, + Back_color,Fore_color, + Brosse_Largeur); + + if (Loupe_Mode) + { + Calculer_dimensions_clipees_zoom(&Debut_X,&Debut_Y,&Largeur,&Hauteur); + Debut_Compteur_X=Debut_X-(X-Brosse_Decalage_X); + Debut_Compteur_Y=Debut_Y-(Y-Brosse_Decalage_Y); + + if ( (Largeur>0) && (Hauteur>0) ) + { + // Corrections dues au Zoom: + Debut_X=(Debut_X-Loupe_Decalage_X)*Loupe_Facteur; + Debut_Y=(Debut_Y-Loupe_Decalage_Y)*Loupe_Facteur; + Hauteur=Debut_Y+(Hauteur*Loupe_Facteur); + if (Hauteur>Menu_Ordonnee) + Hauteur=Menu_Ordonnee; + + Display_brush_Mono_zoom(Principal_X_Zoom+Debut_X,Debut_Y, + Debut_Compteur_X,Debut_Compteur_Y, + Largeur,Hauteur, + Back_color,Fore_color, + Brosse_Largeur, + Buffer_de_ligne_horizontale); + + } + } + } + else + { + if ((Smear_Mode) && (Shade_Table==Shade_Table_gauche)) + { + if (Smear_Debut) + { + if ((Largeur>0) && (Hauteur>0)) + Copier_une_partie_d_image_dans_une_autre(Principal_Ecran, + Debut_X,Debut_Y, + Largeur,Hauteur, + Principal_Largeur_image, + Smear_Brosse, + Debut_Compteur_X, + Debut_Compteur_Y, + Smear_Brosse_Largeur); + //UPDATERECT + Smear_Debut=0; + } + else + { + for (Pos_Y=Debut_Y,Compteur_Y=Debut_Compteur_Y;Compteur_Y=Smear_Min_Y) && (Compteur_X>=Smear_Min_X) ) + Afficher_pixel(Pos_X,Pos_Y,Smear_Brosse[Position]); + Smear_Brosse[Position]=Couleur_temporaire; + } + + UpdateRect(Max(Debut_X,0),Max(Debut_Y,0), + Fin_Compteur_X,Fin_Compteur_Y + ); + + } + + Smear_Min_X=Debut_Compteur_X; + Smear_Min_Y=Debut_Compteur_Y; + Smear_Max_X=Fin_Compteur_X; + Smear_Max_Y=Fin_Compteur_Y; + } + else + { + for (Pos_Y=Debut_Y,Compteur_Y=Debut_Compteur_Y;Compteur_Y0) && (Hauteur>0) ) + Display_brush_Mono(Debut_X-Principal_Decalage_X, + Debut_Y-Principal_Decalage_Y, + Debut_Compteur_X,Debut_Compteur_Y, + Largeur,Hauteur, + 0,Fore_color, + TAILLE_MAXI_PINCEAU); + + if (Loupe_Mode) + { + Calculer_dimensions_clipees_zoom(&Debut_X,&Debut_Y,&Largeur,&Hauteur); + Debut_Compteur_X=Debut_X-(X-Pinceau_Decalage_X); + Debut_Compteur_Y=Debut_Y-(Y-Pinceau_Decalage_Y); + + if ( (Largeur>0) && (Hauteur>0) ) + { + // Corrections dues au Zoom: + Debut_X=(Debut_X-Loupe_Decalage_X)*Loupe_Facteur; + Debut_Y=(Debut_Y-Loupe_Decalage_Y)*Loupe_Facteur; + Hauteur=Debut_Y+(Hauteur*Loupe_Facteur); + if (Hauteur>Menu_Ordonnee) + Hauteur=Menu_Ordonnee; + + Display_brush_Mono_zoom(Principal_X_Zoom+Debut_X,Debut_Y, + Debut_Compteur_X,Debut_Compteur_Y, + Largeur,Hauteur, + 0,Fore_color, + TAILLE_MAXI_PINCEAU, + Buffer_de_ligne_horizontale); + + } + } + + Brosse=Temp; + } + else + { + if ((Smear_Mode) && (Shade_Table==Shade_Table_gauche)) + { + if (Smear_Debut) + { + if ((Largeur>0) && (Hauteur>0)) + Copier_une_partie_d_image_dans_une_autre(Principal_Ecran, + Debut_X,Debut_Y, + Largeur,Hauteur, + Principal_Largeur_image, + Smear_Brosse, + Debut_Compteur_X, + Debut_Compteur_Y, + Smear_Brosse_Largeur); + // UPDATERECT + Smear_Debut=0; + } + else + { + for (Pos_Y=Debut_Y,Compteur_Y=Debut_Compteur_Y;Compteur_Y=Smear_Min_Y) && (Compteur_X>=Smear_Min_X) ) + Afficher_pixel(Pos_X,Pos_Y,Smear_Brosse[Position]); + Smear_Brosse[Position]=Couleur_temporaire; + } + } + + UpdateRect(Debut_X,Debut_Y, + Fin_Compteur_X,Fin_Compteur_Y + ); + + Smear_Min_X=Debut_Compteur_X; + Smear_Min_Y=Debut_Compteur_Y; + Smear_Max_X=Fin_Compteur_X; + Smear_Max_Y=Fin_Compteur_Y; + } + else + { + for (Pos_Y=Debut_Y,Compteur_Y=Debut_Compteur_Y;Compteur_Y=Limite_Gauche) + && (Pinceau_X<=Limite_Droite) + && (Pinceau_Y>=Limite_Haut) + && (Pinceau_Y<=Limite_Bas) ) + { + Pixel_Preview(Pinceau_X,Pinceau_Y,Lit_pixel_dans_ecran_courant(Pinceau_X,Pinceau_Y)); + Mettre_Ecran_A_Jour(Pinceau_X,Pinceau_Y,1,1); + } + break; + case FORME_PINCEAU_BROSSE_COULEUR : // Brosse en couleur + case FORME_PINCEAU_BROSSE_MONOCHROME : // Brosse monochrome + Debut_X=X-Brosse_Decalage_X; + Debut_Y=Y-Brosse_Decalage_Y; + Largeur=Brosse_Largeur; + Hauteur=Brosse_Hauteur; + Calculer_dimensions_clipees(&Debut_X,&Debut_Y,&Largeur,&Hauteur); + Debut_Compteur_X=Debut_X-(X-Brosse_Decalage_X); + Debut_Compteur_Y=Debut_Y-(Y-Brosse_Decalage_Y); + Fin_Compteur_X=Debut_Compteur_X+Largeur; + Fin_Compteur_Y=Debut_Compteur_Y+Hauteur; + + if ( (Largeur>0) && (Hauteur>0) ) + Clear_brush(Debut_X-Principal_Decalage_X, + Debut_Y-Principal_Decalage_Y, + Debut_Compteur_X,Debut_Compteur_Y, + Largeur,Hauteur,Back_color, + Principal_Largeur_image); + + if (Loupe_Mode) + { + Calculer_dimensions_clipees_zoom(&Debut_X,&Debut_Y,&Largeur,&Hauteur); + Debut_Compteur_X=Debut_X; + Debut_Compteur_Y=Debut_Y; + + if ( (Largeur>0) && (Hauteur>0) ) + { + // Corrections dues au Zoom: + Debut_X=(Debut_X-Loupe_Decalage_X)*Loupe_Facteur; + Debut_Y=(Debut_Y-Loupe_Decalage_Y)*Loupe_Facteur; + Hauteur=Debut_Y+(Hauteur*Loupe_Facteur); + if (Hauteur>Menu_Ordonnee) + Hauteur=Menu_Ordonnee; + + Clear_brush_zoom(Principal_X_Zoom+Debut_X,Debut_Y, + Debut_Compteur_X,Debut_Compteur_Y, + Largeur,Hauteur,Back_color, + Principal_Largeur_image, + Buffer_de_ligne_horizontale); + } + } + break; + default: // Pinceau + Debut_X=X-Pinceau_Decalage_X; + Debut_Y=Y-Pinceau_Decalage_Y; + Largeur=Pinceau_Largeur; + Hauteur=Pinceau_Hauteur; + Calculer_dimensions_clipees(&Debut_X,&Debut_Y,&Largeur,&Hauteur); + Debut_Compteur_X=Debut_X-(X-Pinceau_Decalage_X); + Debut_Compteur_Y=Debut_Y-(Y-Pinceau_Decalage_Y); + Fin_Compteur_X=Debut_Compteur_X+Largeur; + Fin_Compteur_Y=Debut_Compteur_Y+Hauteur; + + Temp=Brosse; + Brosse=Pinceau_Sprite; + + if ( (Largeur>0) && (Hauteur>0) ) + { + Clear_brush(Debut_X-Principal_Decalage_X, + Debut_Y-Principal_Decalage_Y, + Debut_Compteur_X,Debut_Compteur_Y, + Largeur,Hauteur,0, + Principal_Largeur_image); + } + + if (Loupe_Mode) + { + Calculer_dimensions_clipees_zoom(&Debut_X,&Debut_Y,&Largeur,&Hauteur); + Debut_Compteur_X=Debut_X; + Debut_Compteur_Y=Debut_Y; + + if ( (Largeur>0) && (Hauteur>0) ) + { + // Corrections dues au Zoom: + Debut_X=(Debut_X-Loupe_Decalage_X)*Loupe_Facteur; + Debut_Y=(Debut_Y-Loupe_Decalage_Y)*Loupe_Facteur; + Hauteur=Debut_Y+(Hauteur*Loupe_Facteur); + if (Hauteur>Menu_Ordonnee) + Hauteur=Menu_Ordonnee; + + Clear_brush_zoom(Principal_X_Zoom+Debut_X,Debut_Y, + Debut_Compteur_X,Debut_Compteur_Y, + Largeur,Hauteur,0, + Principal_Largeur_image, + Buffer_de_ligne_horizontale); + } + } + + Brosse=Temp; + break; + } +} + + + +void Capturer_brosse(short Debut_X,short Debut_Y,short Fin_X,short Fin_Y,short Effacement) +{ + short Temporaire; + short Pos_X; + short Pos_Y; + word Nouvelle_Brosse_Largeur; + word Nouvelle_Brosse_Hauteur; + + + // On commence par "redresser" les bornes: + if (Debut_X>Fin_X) + { + Temporaire=Debut_X; + Debut_X =Fin_X; + Fin_X =Temporaire; + } + if (Debut_Y>Fin_Y) + { + Temporaire=Debut_Y; + Debut_Y =Fin_Y; + Fin_Y =Temporaire; + } + + // On ne capture la nouvelle brosse que si elle est au moins partiellement + // dans l'image: + + if ((Debut_XPrincipal_Largeur_image) + Nouvelle_Brosse_Largeur=Principal_Largeur_image-Debut_X; + if (Debut_Y+Nouvelle_Brosse_Hauteur>Principal_Hauteur_image) + Nouvelle_Brosse_Hauteur=Principal_Hauteur_image-Debut_Y; + + if ( (((long)Brosse_Hauteur)*Brosse_Largeur) != + (((long)Nouvelle_Brosse_Hauteur)*Nouvelle_Brosse_Largeur) ) + { + free(Brosse); + Brosse=(byte *)malloc(((long)Nouvelle_Brosse_Hauteur)*Nouvelle_Brosse_Largeur); + if (!Brosse) + { + Erreur(0); + + Brosse=(byte *)malloc(1*1); + Nouvelle_Brosse_Hauteur=Nouvelle_Brosse_Largeur=1; + *Brosse=Fore_color; + } + } + Brosse_Largeur=Nouvelle_Brosse_Largeur; + Brosse_Hauteur=Nouvelle_Brosse_Hauteur; + + free(Smear_Brosse); + Smear_Brosse_Largeur=(Brosse_Largeur>TAILLE_MAXI_PINCEAU)?Brosse_Largeur:TAILLE_MAXI_PINCEAU; + Smear_Brosse_Hauteur=(Brosse_Hauteur>TAILLE_MAXI_PINCEAU)?Brosse_Hauteur:TAILLE_MAXI_PINCEAU; + Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Hauteur)*Smear_Brosse_Largeur); + + if (!Smear_Brosse) // On ne peut même pas allouer la brosse du smear! + { + Erreur(0); + + free(Brosse); + Brosse=(byte *)malloc(1*1); + Brosse_Hauteur=1; + Brosse_Largeur=1; + + Smear_Brosse=(byte *)malloc(TAILLE_MAXI_PINCEAU*TAILLE_MAXI_PINCEAU); + Smear_Brosse_Hauteur=TAILLE_MAXI_PINCEAU; + Smear_Brosse_Largeur=TAILLE_MAXI_PINCEAU; + } + + Copier_image_dans_brosse(Debut_X,Debut_Y,Brosse_Largeur,Brosse_Hauteur,Principal_Largeur_image); + + // On regarde s'il faut effacer quelque chose: + if (Effacement) + { + for (Pos_Y=Debut_Y;Pos_Y>1); + Brosse_Decalage_Y=(Brosse_Hauteur>>1); + } +} + + +void Rotate_90_deg() +{ + short Temporaire; + byte * Nouvelle_Brosse; + + Nouvelle_Brosse=(byte *)malloc(((long)Brosse_Hauteur)*Brosse_Largeur); + if (Nouvelle_Brosse) + { + Rotate_90_deg_LOWLEVEL(Brosse,Nouvelle_Brosse); + free(Brosse); + Brosse=Nouvelle_Brosse; + + Temporaire=Brosse_Largeur; + Brosse_Largeur=Brosse_Hauteur; + Brosse_Hauteur=Temporaire; + + Temporaire=Smear_Brosse_Largeur; + Smear_Brosse_Largeur=Smear_Brosse_Hauteur; + Smear_Brosse_Hauteur=Temporaire; + + // On centre la prise sur la brosse + Brosse_Decalage_X=(Brosse_Largeur>>1); + Brosse_Decalage_Y=(Brosse_Hauteur>>1); + } + else + Erreur(0); +} + + +void Remap_brosse(void) +{ + short Pos_X; // Variable de balayage de la brosse + short Pos_Y; // Variable de balayage de la brosse + byte Utilisee[256]; // Tableau de booléens "La couleur est utilisée" + int Couleur; + + + // On commence par initialiser le tableau de booléens à faux + for (Couleur=0;Couleur<=255;Couleur++) + Utilisee[Couleur]=0; + + // On calcule la table d'utilisation des couleurs + for (Pos_Y=0;Pos_Y>1); + Brosse_Decalage_Y=(Brosse_Hauteur>>1); + + free(Temporaire); // Libération de l'ancienne brosse + + // Réallocation d'un buffer de Smear + free(Smear_Brosse); + Smear_Brosse_Largeur=(Brosse_Largeur>TAILLE_MAXI_PINCEAU)?Brosse_Largeur:TAILLE_MAXI_PINCEAU; + Smear_Brosse_Hauteur=(Brosse_Hauteur>TAILLE_MAXI_PINCEAU)?Brosse_Hauteur:TAILLE_MAXI_PINCEAU; + Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Largeur)*Smear_Brosse_Hauteur); + } + else + Erreur(0); // Pas assez de mémoire! +} + + +void Nibble_brush(void) +{ + long /*Pos,*/Pos_X,Pos_Y; + byte Etat; + byte * Nouvelle_brosse; + byte * Temporaire; + word Largeur; + word Hauteur; + + if ( (Brosse_Largeur>2) && (Brosse_Hauteur>2) ) + { + Largeur=Brosse_Largeur-2; + Hauteur=Brosse_Hauteur-2; + Nouvelle_brosse=(byte *)malloc(((long)Largeur)*Hauteur); + + if (Nouvelle_brosse) + { + // On copie la brosse courante dans la nouvelle + Copier_une_partie_d_image_dans_une_autre(Brosse, // Source + 1, + 1, + Largeur, + Hauteur, + Brosse_Largeur, + Nouvelle_brosse, // Destination + 0, + 0, + Largeur); + + // On intervertit la nouvelle et l'ancienne brosse: + Temporaire=Brosse; + Brosse=Nouvelle_brosse; + Brosse_Largeur-=2; + Brosse_Hauteur-=2; + Largeur+=2; + Hauteur+=2; + + // 1er balayage (horizontal) + for (Pos_Y=0; Pos_Y0) + Pixel_dans_brosse(Pos_X-1,Pos_Y,Back_color); + Etat=0; + } + } + else + { + if (!Etat) + { + Pixel_dans_brosse(Pos_X,Pos_Y,Back_color); + Etat=1; + } + } + } + // Cas du dernier pixel à droite de la ligne + if (Temporaire[((Pos_Y+1)*Largeur)+Pos_X+1]==Back_color) + Pixel_dans_brosse(Pos_X-1,Pos_Y,Back_color); + } + + // 2ème balayage (vertical) + for (Pos_X=0; Pos_X0) + Pixel_dans_brosse(Pos_X,Pos_Y-1,Back_color); + Etat=0; + } + } + else + { + if (!Etat) + { + Pixel_dans_brosse(Pos_X,Pos_Y,Back_color); + Etat=1; + } + } + } + // Cas du dernier pixel en bas de la colonne + if (Temporaire[((Pos_Y+1)*Largeur)+Pos_X+1]==Back_color) + Pixel_dans_brosse(Pos_X,Pos_Y-1,Back_color); + } + + // On recentre la prise sur la brosse + Brosse_Decalage_X=(Brosse_Largeur>>1); + Brosse_Decalage_Y=(Brosse_Hauteur>>1); + + free(Temporaire); // Libération de l'ancienne brosse + + // Réallocation d'un buffer de Smear + free(Smear_Brosse); + Smear_Brosse_Largeur=(Brosse_Largeur>TAILLE_MAXI_PINCEAU)?Brosse_Largeur:TAILLE_MAXI_PINCEAU; + Smear_Brosse_Hauteur=(Brosse_Hauteur>TAILLE_MAXI_PINCEAU)?Brosse_Hauteur:TAILLE_MAXI_PINCEAU; + Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Largeur)*Smear_Brosse_Hauteur); + } + else + Erreur(0); // Pas assez de mémoire! + } +} + + + +void Capturer_brosse_au_lasso(int Vertices, short * Points,short Effacement) +{ + short Debut_X=Limite_Droite+1; + short Debut_Y=Limite_Bas+1; + short Fin_X=Limite_Gauche-1; + short Fin_Y=Limite_Haut-1; + short Temporaire; + short Pos_X; + short Pos_Y; + word Nouvelle_Brosse_Largeur; + word Nouvelle_Brosse_Hauteur; + + + // On recherche les bornes de la brosse: + for (Temporaire=0; TemporaireFin_X) + Fin_X=Pos_X; + if (Pos_YFin_Y) + Fin_Y=Pos_Y; + } + + // On clippe ces bornes à l'écran: + if (Debut_XLimite_Droite) + Fin_X=Limite_Droite; + if (Debut_YLimite_Bas) + Fin_Y=Limite_Bas; + + // On ne capture la nouvelle brosse que si elle est au moins partiellement + // dans l'image: + + if ((Debut_XTAILLE_MAXI_PINCEAU)?Brosse_Largeur:TAILLE_MAXI_PINCEAU; + Smear_Brosse_Hauteur=(Brosse_Hauteur>TAILLE_MAXI_PINCEAU)?Brosse_Hauteur:TAILLE_MAXI_PINCEAU; + Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Hauteur)*Smear_Brosse_Largeur); + + if (!Smear_Brosse) // On ne peut même pas allouer la brosse du smear! + { + Erreur(0); + + free(Brosse); + Brosse=(byte *)malloc(1*1); + Brosse_Hauteur=1; + Brosse_Largeur=1; + + Smear_Brosse=(byte *)malloc(TAILLE_MAXI_PINCEAU*TAILLE_MAXI_PINCEAU); + Smear_Brosse_Hauteur=TAILLE_MAXI_PINCEAU; + Smear_Brosse_Largeur=TAILLE_MAXI_PINCEAU; + } + + Brosse_Decalage_X=Debut_X; + Brosse_Decalage_Y=Debut_Y; + Pixel_figure=Pixel_figure_Dans_brosse; + + memset(Brosse,Back_color,(long)Brosse_Largeur*Brosse_Hauteur); + Polyfill_General(Vertices,Points,~Back_color); + + // On retrace les bordures du lasso: + for (Temporaire=1; Temporaire>1); + Brosse_Decalage_Y=(Brosse_Hauteur>>1); + } +} + + + +//------------------------- Etirement de la brosse --------------------------- + +void Etirer_brosse(short X1, short Y1, short X2, short Y2) +{ + int Offset,Ligne,Colonne; + byte * New_Brosse; + + int New_Brosse_Largeur; // Largeur de la nouvelle brosse + int New_Brosse_Hauteur; // Hauteur de la nouvelle brosse + + int Pos_X_dans_brosse; // Position courante dans l'ancienne brosse + int Pos_Y_dans_brosse; + int Delta_X_dans_brosse; // "Vecteur incrémental" du point précédent + int Delta_Y_dans_brosse; + int Pos_X_initial; // Position X de début de parcours de ligne + int Dx,Dy; + + Dx=(X1=0) + Pos_X_initial = 0; // Pas d'inversion en X de la brosse + else + Pos_X_initial = (Brosse_Largeur<<16)-1; // Inversion en X de la brosse + + free(Smear_Brosse); // On libère un peu de mémoire + + if ((New_Brosse=((byte *)malloc(New_Brosse_Largeur*New_Brosse_Hauteur)))) + { + Offset=0; + + // Calcul de la valeur initiale de Pos_Y: + if (Dy>=0) + Pos_Y_dans_brosse=0; // Pas d'inversion en Y de la brosse + else + Pos_Y_dans_brosse=(Brosse_Hauteur<<16)-1; // Inversion en Y de la brosse + + // Pour chaque ligne + for (Ligne=0;Ligne>16,Pos_Y_dans_brosse>>16); + // On passe à la colonne de brosse suivante: + Pos_X_dans_brosse+=Delta_X_dans_brosse; + // On passe au pixel suivant de la nouvelle brosse: + Offset++; + } + + // On passe à la ligne de brosse suivante: + Pos_Y_dans_brosse+=Delta_Y_dans_brosse; + } + + free(Brosse); + Brosse=New_Brosse; + + Brosse_Largeur=New_Brosse_Largeur; + Brosse_Hauteur=New_Brosse_Hauteur; + + Smear_Brosse_Largeur=(Brosse_Largeur>TAILLE_MAXI_PINCEAU)?Brosse_Largeur:TAILLE_MAXI_PINCEAU; + Smear_Brosse_Hauteur=(Brosse_Hauteur>TAILLE_MAXI_PINCEAU)?Brosse_Hauteur:TAILLE_MAXI_PINCEAU; + Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Hauteur)*Smear_Brosse_Largeur); + + if (!Smear_Brosse) // On ne peut même pas allouer la brosse du smear! + { + Erreur(0); + + free(Brosse); + Brosse=(byte *)malloc(1*1); + Brosse_Hauteur=1; + Brosse_Largeur=1; + + Smear_Brosse=(byte *)malloc(TAILLE_MAXI_PINCEAU*TAILLE_MAXI_PINCEAU); + Smear_Brosse_Hauteur=TAILLE_MAXI_PINCEAU; + Smear_Brosse_Largeur=TAILLE_MAXI_PINCEAU; + } + + Brosse_Decalage_X=(Brosse_Largeur>>1); + Brosse_Decalage_Y=(Brosse_Hauteur>>1); + } + else + { + // Ici la libération de mémoire n'a pas suffit donc on remet dans l'état + // où c'etait avant. On a juste à réallouer la Smear_Brosse car il y a + // normalement la place pour elle puisque rien d'autre n'a pu être alloué + // entre temps. + Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Hauteur)*Smear_Brosse_Largeur); + Erreur(0); + } +} + + + +void Etirer_brosse_preview(short X1, short Y1, short X2, short Y2) +{ + int Pos_X_src,Pos_Y_src; + int Pos_X_src_Initiale,Pos_Y_src_Initiale; + int Delta_X,Delta_Y; + int Pos_X_dest,Pos_Y_dest; + int Pos_X_dest_Initiale,Pos_Y_dest_Initiale; + int Pos_X_dest_Finale,Pos_Y_dest_Finale; + int Largeur_dest,Hauteur_dest; + byte Couleur; + + + // 1er calcul des positions destination extremes: + Pos_X_dest_Initiale=Min(X1,X2); + Pos_Y_dest_Initiale=Min(Y1,Y2); + Pos_X_dest_Finale =Max(X1,X2); + Pos_Y_dest_Finale =Max(Y1,Y2); + + // Calcul des dimensions de la destination: + Largeur_dest=Pos_X_dest_Finale-Pos_X_dest_Initiale+1; + Hauteur_dest=Pos_Y_dest_Finale-Pos_Y_dest_Initiale+1; + + // Calcul des vecteurs d'incrémentation : + Delta_X=(Brosse_Largeur<<16)/Largeur_dest; + Delta_Y=(Brosse_Hauteur<<16)/Hauteur_dest; + + // 1er calcul de la position X initiale dans la source: + Pos_X_src_Initiale=(Brosse_Largeur<<16)* + (Max(Pos_X_dest_Initiale,Limite_Gauche)- + Pos_X_dest_Initiale)/Largeur_dest; + // Calcul du clip de la destination: + Pos_X_dest_Initiale=Max(Pos_X_dest_Initiale,Limite_Gauche); + Pos_X_dest_Finale =Min(Pos_X_dest_Finale ,Limite_visible_Droite); + // On discute selon l'inversion en X + if (X1>X2) + { + // Inversion -> Inversion du signe de Delta_X + Delta_X=-Delta_X; + Pos_X_src_Initiale=(Brosse_Largeur<<16)-1-Pos_X_src_Initiale; + } + + // 1er calcul de la position Y initiale dans la source: + Pos_Y_src_Initiale=(Brosse_Hauteur<<16)* + (Max(Pos_Y_dest_Initiale,Limite_Haut)- + Pos_Y_dest_Initiale)/Hauteur_dest; + // Calcul du clip de la destination: + Pos_Y_dest_Initiale=Max(Pos_Y_dest_Initiale,Limite_Haut); + Pos_Y_dest_Finale =Min(Pos_Y_dest_Finale ,Limite_visible_Bas); + // On discute selon l'inversion en Y + if (Y1>Y2) + { + // Inversion -> Inversion du signe de Delta_Y + Delta_Y=-Delta_Y; + Pos_Y_src_Initiale=(Brosse_Hauteur<<16)-1-Pos_Y_src_Initiale; + } + + // Pour chaque ligne : + Pos_Y_src=Pos_Y_src_Initiale; + for (Pos_Y_dest=Pos_Y_dest_Initiale;Pos_Y_dest<=Pos_Y_dest_Finale;Pos_Y_dest++) + { + // Pour chaque colonne: + Pos_X_src=Pos_X_src_Initiale; + for (Pos_X_dest=Pos_X_dest_Initiale;Pos_X_dest<=Pos_X_dest_Finale;Pos_X_dest++) + { + Couleur=Lit_pixel_dans_brosse(Pos_X_src>>16,Pos_Y_src>>16); + if (Couleur!=Back_color) + Pixel_Preview(Pos_X_dest,Pos_Y_dest,Couleur); + + Pos_X_src+=Delta_X; + } + + Pos_Y_src+=Delta_Y; + } + UpdateRect(Pos_X_dest_Initiale,Pos_Y_dest_Initiale,Largeur_dest,Hauteur_dest); +} + + + +//------------------------- Rotation de la brosse --------------------------- + +#define INDEFINI (-1.0e20F) +float * ScanY_Xt[2]; +float * ScanY_Yt[2]; +float * ScanY_X[2]; + + +void Interpoler_texture(int Debut_X,int Debut_Y,int Xt1,int Yt1, + int Fin_X ,int Fin_Y ,int Xt2,int Yt2,int Hauteur) +{ + int Pos_X,Pos_Y; + int Incr_X,Incr_Y; + int i,Cumul; + int Delta_X,Delta_Y; + int Delta_Xt=Xt2-Xt1; + int Delta_Yt=Yt2-Yt1; + int Delta_X2=Fin_X-Debut_X; + int Delta_Y2=Fin_Y-Debut_Y; + float Xt,Yt; + + + Pos_X=Debut_X; + Pos_Y=Debut_Y; + + if (Debut_XDelta_Y) + { + Cumul=Delta_X>>1; + for (i=0; i<=Delta_X; i++) + { + if (Cumul>=Delta_X) + { + Cumul-=Delta_X; + Pos_Y+=Incr_Y; + } + + if ((Pos_Y>=0) && (Pos_Y=ScanY_X[0][Pos_Y]) + { + if ((ScanY_X[1][Pos_Y]==INDEFINI) // Droit non défini + || (Pos_X>ScanY_X[1][Pos_Y])) + { + ScanY_X[1][Pos_Y]=Pos_X; + ScanY_Xt[1][Pos_Y]=Xt; + ScanY_Yt[1][Pos_Y]=Yt; + } + } + else + { + if (ScanY_X[1][Pos_Y]==INDEFINI) // Droit non défini + { + ScanY_X[1][Pos_Y]=ScanY_X[0][Pos_Y]; + ScanY_Xt[1][Pos_Y]=ScanY_Xt[0][Pos_Y]; + ScanY_Yt[1][Pos_Y]=ScanY_Yt[0][Pos_Y]; + ScanY_X[0][Pos_Y]=Pos_X; + ScanY_Xt[0][Pos_Y]=Xt; + ScanY_Yt[0][Pos_Y]=Yt; + } + else + { + ScanY_X[0][Pos_Y]=Pos_X; + ScanY_Xt[0][Pos_Y]=Xt; + ScanY_Yt[0][Pos_Y]=Yt; + } + } + } + } + Pos_X+=Incr_X; + Cumul+=Delta_Y; + } + } + else + { + Cumul=Delta_Y>>1; + for (i=0; i<=Delta_Y; i++) + { + if (Cumul>=Delta_Y) + { + Cumul-=Delta_Y; + Pos_X+=Incr_X; + } + + if ((Pos_Y>=0) && (Pos_Y=ScanY_X[0][Pos_Y]) + { + if ((ScanY_X[1][Pos_Y]==INDEFINI) // Droit non défini + || (Pos_X>ScanY_X[1][Pos_Y])) + { + ScanY_X[1][Pos_Y]=Pos_X; + ScanY_Xt[1][Pos_Y]=Xt; + ScanY_Yt[1][Pos_Y]=Yt; + } + } + else + { + if (ScanY_X[1][Pos_Y]==INDEFINI) // Droit non défini + { + ScanY_X[1][Pos_Y]=ScanY_X[0][Pos_Y]; + ScanY_Xt[1][Pos_Y]=ScanY_Xt[0][Pos_Y]; + ScanY_Yt[1][Pos_Y]=ScanY_Yt[0][Pos_Y]; + ScanY_X[0][Pos_Y]=Pos_X; + ScanY_Xt[0][Pos_Y]=Xt; + ScanY_Yt[0][Pos_Y]=Yt; + } + else + { + ScanY_X[0][Pos_Y]=Pos_X; + ScanY_Xt[0][Pos_Y]=Xt; + ScanY_Yt[0][Pos_Y]=Yt; + } + } + } + } + Pos_Y+=Incr_Y; + Cumul+=Delta_X; + } + } +} + + + +void Calculer_quad_texture(int X1,int Y1,int Xt1,int Yt1, + int X2,int Y2,int Xt2,int Yt2, + int X3,int Y3,int Xt3,int Yt3, + int X4,int Y4,int Xt4,int Yt4, + byte * Buffer, int Largeur, int Hauteur) +{ + int Xmin,/*Xmax,*/Ymin/*,Ymax*/; + int X,Y,Xt,Yt; + int Debut_X,Fin_X,Largeur_ligne; + float Temp; + //byte Couleur; + + Xmin=Min(Min(X1,X2),Min(X3,X4)); + Ymin=Min(Min(Y1,Y2),Min(Y3,Y4)); + + ScanY_Xt[0]=(float *)malloc(Hauteur*sizeof(float)); + ScanY_Xt[1]=(float *)malloc(Hauteur*sizeof(float)); + ScanY_Yt[0]=(float *)malloc(Hauteur*sizeof(float)); + ScanY_Yt[1]=(float *)malloc(Hauteur*sizeof(float)); + ScanY_X[0] =(float *)malloc(Hauteur*sizeof(float)); + ScanY_X[1] =(float *)malloc(Hauteur*sizeof(float)); + + // Remplir avec des valeurs égales à INDEFINI. + for (Y=0; Y>1); + Debut_Y=1-(Brosse_Hauteur>>1); + Fin_X=Debut_X+Brosse_Largeur-1; + Fin_Y=Debut_Y+Brosse_Hauteur-1; + + Transformer_point(Debut_X,Debut_Y, cosA,sinA, &X1,&Y1); + Transformer_point(Fin_X ,Debut_Y, cosA,sinA, &X2,&Y2); + Transformer_point(Debut_X,Fin_Y , cosA,sinA, &X3,&Y3); + Transformer_point(Fin_X ,Fin_Y , cosA,sinA, &X4,&Y4); + + // Calcul des nouvelles dimensions de la brosse: + Xmin=Min(Min((int)X1,(int)X2),Min((int)X3,(int)X4)); + Xmax=Max(Max((int)X1,(int)X2),Max((int)X3,(int)X4)); + Ymin=Min(Min((int)Y1,(int)Y2),Min((int)Y3,(int)Y4)); + Ymax=Max(Max((int)Y1,(int)Y2),Max((int)Y3,(int)Y4)); + + New_Brosse_Largeur=Xmax+1-Xmin; + New_Brosse_Hauteur=Ymax+1-Ymin; + + free(Smear_Brosse); // On libère un peu de mémoire + + if ((New_Brosse=((byte *)malloc(New_Brosse_Largeur*New_Brosse_Hauteur)))) + { + // Et maintenant on calcule la nouvelle brosse tournée. + Calculer_quad_texture(X1,Y1, 0, 0, + X2,Y2,Brosse_Largeur-1, 0, + X3,Y3, 0,Brosse_Hauteur-1, + X4,Y4,Brosse_Largeur-1,Brosse_Hauteur-1, + New_Brosse,New_Brosse_Largeur,New_Brosse_Hauteur); + + free(Brosse); + Brosse=New_Brosse; + + Brosse_Largeur=New_Brosse_Largeur; + Brosse_Hauteur=New_Brosse_Hauteur; + + Smear_Brosse_Largeur=(Brosse_Largeur>TAILLE_MAXI_PINCEAU)?Brosse_Largeur:TAILLE_MAXI_PINCEAU; + Smear_Brosse_Hauteur=(Brosse_Hauteur>TAILLE_MAXI_PINCEAU)?Brosse_Hauteur:TAILLE_MAXI_PINCEAU; + Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Hauteur)*Smear_Brosse_Largeur); + + if (!Smear_Brosse) // On ne peut même pas allouer la brosse du smear! + { + Erreur(0); + + free(Brosse); + Brosse=(byte *)malloc(1*1); + Brosse_Hauteur=1; + Brosse_Largeur=1; + + Smear_Brosse=(byte *)malloc(TAILLE_MAXI_PINCEAU*TAILLE_MAXI_PINCEAU); + Smear_Brosse_Hauteur=TAILLE_MAXI_PINCEAU; + Smear_Brosse_Largeur=TAILLE_MAXI_PINCEAU; + } + + Brosse_Decalage_X=(Brosse_Largeur>>1); + Brosse_Decalage_Y=(Brosse_Hauteur>>1); + } + else + { + // Ici la libération de mémoire n'a pas suffit donc on remet dans l'état + // où c'etait avant. On a juste à réallouer la Smear_Brosse car il y a + // normalement la place pour elle puisque rien d'autre n'a pu être alloué + // entre temps. + Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Hauteur)*Smear_Brosse_Largeur); + Erreur(0); + } +} + + + +void Dessiner_quad_texture_preview(int X1,int Y1,int Xt1,int Yt1, + int X2,int Y2,int Xt2,int Yt2, + int X3,int Y3,int Xt3,int Yt3, + int X4,int Y4,int Xt4,int Yt4) +{ + int Xmin,Xmax,Ymin,Ymax; + int X,Y,Xt,Yt; + int Y_,Ymin_; + int Debut_X,Fin_X,Largeur,Hauteur; + float Temp; + byte Couleur; + + Xmin=Min(Min(X1,X2),Min(X3,X4)); + Xmax=Max(Max(X1,X2),Max(X3,X4)); + Ymin=Min(Min(Y1,Y2),Min(Y3,Y4)); + Ymax=Max(Max(Y1,Y2),Max(Y3,Y4)); + Hauteur=1+Ymax-Ymin; + + ScanY_Xt[0]=(float *)malloc(Hauteur*sizeof(float)); + ScanY_Xt[1]=(float *)malloc(Hauteur*sizeof(float)); + ScanY_Yt[0]=(float *)malloc(Hauteur*sizeof(float)); + ScanY_Yt[1]=(float *)malloc(Hauteur*sizeof(float)); + ScanY_X[0] =(float *)malloc(Hauteur*sizeof(float)); + ScanY_X[1] =(float *)malloc(Hauteur*sizeof(float)); + + // Remplir avec des valeurs égales à INDEFINI. + for (Y=0; YLimite_Bas) Ymax=Limite_Bas; + + for (Y_=Ymin; Y_<=Ymax; Y_++) + { + Y=Y_-Ymin_; + Debut_X=Round(ScanY_X[0][Y]); + Fin_X =Round(ScanY_X[1][Y]); + + Largeur=1+Fin_X-Debut_X; + + if (Debut_XLimite_Droite) Fin_X=Limite_Droite; + + for (X=Debut_X; X<=Fin_X; X++) + { + Temp=(float)(0.5+(float)X-ScanY_X[0][Y])/(float)Largeur; + Xt=Round((float)(ScanY_Xt[0][Y])+(Temp*(ScanY_Xt[1][Y]-ScanY_Xt[0][Y]))); + Yt=Round((float)(ScanY_Yt[0][Y])+(Temp*(ScanY_Yt[1][Y]-ScanY_Yt[0][Y]))); + + Couleur=Lit_pixel_dans_brosse(Xt,Yt); + if (Couleur!=Back_color) + Pixel_Preview(X,Y_,Couleur); + } + } + + free(ScanY_Xt[0]); + free(ScanY_Xt[1]); + free(ScanY_Yt[0]); + free(ScanY_Yt[1]); + free(ScanY_X[0]); + free(ScanY_X[1]); +} + + +void Tourner_brosse_preview(float Angle) +{ + short X1,Y1,X2,Y2,X3,Y3,X4,Y4; + int Debut_X,Fin_X,Debut_Y,Fin_Y; + float cosA=cos(Angle); + float sinA=sin(Angle); + + // Calcul des coordonnées des 4 coins: + // 1 2 + // 3 4 + + Debut_X=1-(Brosse_Largeur>>1); + Debut_Y=1-(Brosse_Hauteur>>1); + Fin_X=Debut_X+Brosse_Largeur-1; + Fin_Y=Debut_Y+Brosse_Hauteur-1; + + Transformer_point(Debut_X,Debut_Y, cosA,sinA, &X1,&Y1); + Transformer_point(Fin_X ,Debut_Y, cosA,sinA, &X2,&Y2); + Transformer_point(Debut_X,Fin_Y , cosA,sinA, &X3,&Y3); + Transformer_point(Fin_X ,Fin_Y , cosA,sinA, &X4,&Y4); + + X1+=Brosse_Centre_rotation_X; + Y1+=Brosse_Centre_rotation_Y; + X2+=Brosse_Centre_rotation_X; + Y2+=Brosse_Centre_rotation_Y; + X3+=Brosse_Centre_rotation_X; + Y3+=Brosse_Centre_rotation_Y; + X4+=Brosse_Centre_rotation_X; + Y4+=Brosse_Centre_rotation_Y; + + // Et maintenant on dessine la brosse tournée. + Dessiner_quad_texture_preview(X1,Y1, 0, 0, + X2,Y2,Brosse_Largeur-1, 0, + X3,Y3, 0,Brosse_Hauteur-1, + X4,Y4,Brosse_Largeur-1,Brosse_Hauteur-1); + Debut_X=Min(Min(X1,X2),Min(X3,X4)); + Fin_X=Max(Max(X1,X2),Max(X3,X4)); + Debut_Y=Min(Min(Y1,Y2),Min(Y3,Y4)); + Fin_Y=Max(Max(Y1,Y2),Max(Y3,Y4)); + UpdateRect(Debut_X,Debut_Y,Fin_X-Debut_X+1,Fin_Y-Debut_Y+1); +} diff --git a/brush.h b/brush.h new file mode 100644 index 00000000..cc73d72a --- /dev/null +++ b/brush.h @@ -0,0 +1,38 @@ +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007-2008 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. +*/ + +#ifndef __BRUSHH__ +#define __BRUSHH__ + +void Capturer_brosse(short Debut_X,short Debut_Y,short Fin_X,short Fin_Y,short Effacement); +void Rotate_90_deg(void); +void Etirer_brosse(short X1, short Y1, short X2, short Y2); +void Etirer_brosse_preview(short X1, short Y1, short X2, short Y2); +void Tourner_brosse(float Angle); +void Tourner_brosse_preview(float Angle); + +void Remap_brosse(void); +void Get_colors_from_brush(void); +void Outline_brush(void); +void Nibble_brush(void); +void Capturer_brosse_au_lasso(int Vertices, short * Points,short Effacement); + +#endif diff --git a/divers.c b/divers.c index 1634614e..0fc1b4ed 100644 --- a/divers.c +++ b/divers.c @@ -140,7 +140,7 @@ void Effacer_image_courante(byte Couleur) void Sensibilite_souris(__attribute__((unused)) word X,__attribute__((unused)) word Y) { - + } int Get_input(void) @@ -201,10 +201,10 @@ int Get_input(void) //Appui sur une touche du clavier Touche = Conversion_Touche(event.key.keysym); Touche_ANSI = Conversion_ANSI(event.key.keysym); - + //Cas particulier: déplacement du curseur avec haut bas gauche droite //On doit interpréter ça comme un mvt de la souris - + if(Touche == Config_Touche[0]) { //[Touche] = Emulation de MOUSE UP @@ -358,7 +358,7 @@ int Get_input(void) Afficher_curseur(); } - // Vidage de toute mise à jour de l'affichage à l'écran qui serait encore en attente. + // Vidage de toute mise à jour de l'affichage à l'écran qui serait encore en attente. // (c'est fait ici car on est sur que cette fonction est apellée partout ou on a besoin d'interragir avec l'utilisateur) Flush_update(); return 1; // Il y a des choses à faire @@ -379,7 +379,7 @@ void Wait_VBL(void) // sans charger inutilement le CPU par du busy-wait (on n'est pas à 10ms près) { const int Delai = 10; - + Uint32 debut; debut = SDL_GetTicks(); // Première attente : le complément de "Delai" millisecondes @@ -389,7 +389,7 @@ void Wait_VBL(void) while (SDL_GetTicks() / Delai <= debut / Delai) { SDL_Delay(1); - } + } } void Pixel_dans_brosse (word X,word Y,byte Couleur) @@ -417,7 +417,7 @@ void Pixel_dans_ecran_courant (word X,word Y,byte Couleur) void Remplacer_une_couleur(byte Ancienne_couleur, byte Nouvelle_couleur) { byte* edi; - + // pour chaque pixel : for(edi = Principal_Ecran;edi < Principal_Ecran + Principal_Hauteur_image * Principal_Largeur_image;edi++) if (*edi == Ancienne_couleur) @@ -428,25 +428,25 @@ void Remplacer_une_couleur(byte Ancienne_couleur, byte Nouvelle_couleur) void Ellipse_Calculer_limites(short Rayon_horizontal,short Rayon_vertical) { - Ellipse_Rayon_horizontal_au_carre = + Ellipse_Rayon_horizontal_au_carre = Rayon_horizontal * Rayon_horizontal; - Ellipse_Rayon_vertical_au_carre = + Ellipse_Rayon_vertical_au_carre = Rayon_vertical * Rayon_vertical; Ellipse_Limite = Ellipse_Rayon_horizontal_au_carre * Ellipse_Rayon_vertical_au_carre; } byte Pixel_dans_ellipse(void) { - uint64_t ediesi = Ellipse_Curseur_X * Ellipse_Curseur_X * Ellipse_Rayon_vertical_au_carre + + uint64_t ediesi = Ellipse_Curseur_X * Ellipse_Curseur_X * Ellipse_Rayon_vertical_au_carre + Ellipse_Curseur_Y * Ellipse_Curseur_Y * Ellipse_Rayon_horizontal_au_carre; if((ediesi) <= Ellipse_Limite) return 255; - + return 0; } byte Pixel_dans_cercle(void) { - if(Cercle_Curseur_X * Cercle_Curseur_X + + if(Cercle_Curseur_X * Cercle_Curseur_X + Cercle_Curseur_Y * Cercle_Curseur_Y <= Cercle_Limite) return 255; return 0; @@ -471,7 +471,7 @@ void Copier_une_partie_d_image_dans_une_autre(byte * Source,word S_Pos_X,word S_ esi+=Largeur_source; edi+=Largeur_destination; } - + } @@ -492,7 +492,7 @@ void Rotate_90_deg_LOWLEVEL(byte * Source,byte * Destination) // Largeur de la source = Hauteur de la destination dx = bx = Brosse_Largeur; - + // Pour chaque ligne for(dx = Brosse_Largeur;dx>0;dx--) { @@ -590,7 +590,7 @@ void Remplacer_toutes_les_couleurs_dans_limites(byte * Table_de_remplacement) *Adresse = Table_de_remplacement[Ancien]; } } -} +} byte Lit_pixel_dans_ecran_backup (word X,word Y) { @@ -649,7 +649,7 @@ byte Effet_Colorize_interpole (word X,word Y,byte Couleur) // (Couleur_dessous*Facteur_A+Couleur*facteur_B)/256 // - // On place dans ESI 3*Couleur_dessous ( = position de cette couleur dans la + // On place dans ESI 3*Couleur_dessous ( = position de cette couleur dans la // palette des teintes) et dans EDI, 3*Couleur. byte Bleu_dessous=Principal_Palette[*(FX_Feedback_Ecran + Y * Principal_Largeur_image + X)].B; byte Bleu=Principal_Palette[Couleur].B; @@ -657,15 +657,15 @@ byte Effet_Colorize_interpole (word X,word Y,byte Couleur) byte Vert=Principal_Palette[Couleur].V; byte Rouge_dessous=Principal_Palette[*(FX_Feedback_Ecran + Y * Principal_Largeur_image + X)].R; byte Rouge=Principal_Palette[Couleur].R; - + // On récupère les 3 composantes RVB // Bleu - Bleu = (Table_de_multiplication_par_Facteur_B[Bleu] + Bleu = (Table_de_multiplication_par_Facteur_B[Bleu] + Table_de_multiplication_par_Facteur_A[Bleu_dessous]) / 256; - Vert = (Table_de_multiplication_par_Facteur_B[Vert] + Vert = (Table_de_multiplication_par_Facteur_B[Vert] + Table_de_multiplication_par_Facteur_A[Vert_dessous]) / 256; - Rouge = (Table_de_multiplication_par_Facteur_B[Rouge] + Rouge = (Table_de_multiplication_par_Facteur_B[Rouge] + Table_de_multiplication_par_Facteur_A[Rouge_dessous]) / 256; return Meilleure_couleur(Rouge,Vert,Bleu); @@ -679,7 +679,7 @@ byte Effet_Colorize_additif (word X,word Y,byte Couleur) byte Bleu=Principal_Palette[Couleur].B; byte Vert=Principal_Palette[Couleur].V; byte Rouge=Principal_Palette[Couleur].R; - + return Meilleure_couleur( Rouge>Rouge_dessous?Rouge:Rouge_dessous, Vert>Vert_dessous?Vert:Vert_dessous, @@ -694,7 +694,7 @@ byte Effet_Colorize_soustractif(word X,word Y,byte Couleur) byte Bleu=Principal_Palette[Couleur].B; byte Vert=Principal_Palette[Couleur].V; byte Rouge=Principal_Palette[Couleur].R; - + return Meilleure_couleur( Rouge0;dx--) + for(dx = Principal_Hauteur_image - Decalage_Y;dx>0;dx--) { // Pour chaque ligne memcpy(edi,esi,ax); @@ -863,7 +863,7 @@ word Get_key(void) } } -void Zoomer_une_ligne(byte* Ligne_originale, byte* Ligne_zoomee, +void Zoomer_une_ligne(byte* Ligne_originale, byte* Ligne_zoomee, word Facteur, word Largeur ) { @@ -880,3 +880,151 @@ void Zoomer_une_ligne(byte* Ligne_originale, byte* Ligne_zoomee, Ligne_originale++; } } + +/*############################################################################*/ + +#if defined(__WIN32__) + #define _WIN32_WINNT 0x0500 + #include +#elif defined(__macosx__) + #include +#elif defined(__BEOS__) || defined(__HAIKU__) + // sysinfo not implemented +#else + #include // sysinfo() for free RAM +#endif + +// Indique quelle est la mémoire disponible +unsigned long Memoire_libre(void) +{ + // On appelle la fonction qui optimise la mémoire libre afin d'en + // regagner un maximum. Sinon, tous les "free" libèrent une mémoire qui + // n'est pas prise en compte par la fonction, et on se retrouve avec un + // manque alarmant de mémoire. + /* + A revoir, mais est-ce vraiment utile? + _heapmin(); + */ + // Memory is no longer relevant. If there is ANY problem or doubt here, + // you can simply return 10*1024*1024 (10Mb), to make the "Pages"something + // memory allocation functions happy. + #if defined(__WIN32__) + MEMORYSTATUSEX mstt; + mstt.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&mstt); + return mstt.ullAvailPhys; + #elif defined(__macosx__) + int mib[2]; + int maxmem; + size_t len; + + mib[0] = CTL_HW; + mib[1] = HW_USERMEM; + len = sizeof(maxmem); + sysctl(mib,2,&maxmem,&len,NULL,0); + return maxmem; + #elif defined(__BEOS__) || defined(__HAIKU__) + // No on BeOS or Haiku + return 10*1024*1024; + #else + struct sysinfo info; + sysinfo(&info); + return info.freeram*info.mem_unit; + #endif +} + + + +// Transformer un nombre (entier naturel) en chaîne +void Num2str(dword Nombre,char * Chaine,byte Taille) +{ + int Indice; + + for (Indice=Taille-1;Indice>=0;Indice--) + { + Chaine[Indice]=(Nombre%10)+'0'; + Nombre/=10; + if (Nombre==0) + for (Indice--;Indice>=0;Indice--) + Chaine[Indice]=' '; + } + Chaine[Taille]='\0'; +} + +// Transformer une chaîne en un entier naturel (renvoie -1 si ch. invalide) +int Str2num(char * Chaine) +{ + int Valeur=0; + + for (;*Chaine;Chaine++) + { + if ( (*Chaine>='0') && (*Chaine<='9') ) + Valeur=(Valeur*10)+(*Chaine-'0'); + else + return -1; + } + return Valeur; +} + + +// Arrondir un nombre réel à la valeur entière la plus proche +short Round(float Valeur) +{ + short Temp=Valeur; + + if (Valeur>=0) + { if ((Valeur-Temp)>= 0.5) Temp++; } + else + { if ((Valeur-Temp)<=-0.5) Temp--; } + + return Temp; +} + +// Arrondir le résultat d'une division à la valeur entière supérieure +short Round_div_max(short Numerateur,short Diviseur) +{ + if (!(Numerateur % Diviseur)) + return (Numerateur/Diviseur); + else + return (Numerateur/Diviseur)+1; +} + +// Retourne le minimum entre deux nombres +int Min(int A,int B) +{ + return (AB)?A:B; +} + + + +// Fonction retournant le libellé d'une mode (ex: " 320x200") +char * Libelle_mode(int Mode) +{ + static char Chaine[24]; + if (! Mode_video[Mode].Fullscreen) + return "window"; + sprintf(Chaine, "%dx%d", Mode_video[Mode].Largeur, Mode_video[Mode].Hauteur); + + return Chaine; +} + +// Trouve un mode video à partir d'une chaine: soit "window", +// soit de la forme "320x200" +// Renvoie -1 si la chaine n'est pas convertible +int Conversion_argument_mode(const char *Argument) +{ + // Je suis paresseux alors je vais juste tester les libellés + int Indice_mode; + for (Indice_mode=0; Indice_mode or write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +******************************************************************************** + + Drawing functions and effects. + */ -#if defined(__WIN32__) - #define _WIN32_WINNT 0x0500 - #include -#elif defined(__macosx__) - #include -#elif defined(__BEOS__) || defined(__HAIKU__) - // sysinfo not implemented -#else - #include // sysinfo() for free RAM -#endif #include #include @@ -46,6 +41,7 @@ #include "pxsimple.h" #include "pxtall.h" #include "pxwide.h" +#include "windows.h" // Fonction qui met à jour la zone de l'image donnée en paramètre sur l'écran. // Tient compte du décalage X et Y et du zoom, et fait tous les controles nécessaires @@ -122,7 +118,7 @@ void Mettre_Ecran_A_Jour(short X, short Y, short Largeur, short Hauteur) Y_effectif = (Y-Loupe_Decalage_Y)*Loupe_Facteur; L_effectif = Largeur * Loupe_Facteur; H_effectif = Hauteur * Loupe_Facteur; - + if (X_effectif < 0) { L_effectif+=X_effectif; @@ -133,7 +129,7 @@ void Mettre_Ecran_A_Jour(short X, short Y, short Largeur, short Hauteur) Diff = X_effectif+L_effectif-Largeur_ecran; if (Diff>0) L_effectif -=Diff; - + // Clipping en Y if (Y_effectif < 0) { @@ -156,594 +152,7 @@ void Mettre_Ecran_A_Jour(short X, short Y, short Largeur, short Hauteur) } } -byte Meilleure_couleur(byte R,byte V,byte B) -{ - short Coul; - int Delta_R,Delta_V,Delta_B; - int Dist; - int Best_dist=0x7FFFFFFF; - byte Best_color=0; - for (Coul=0; Coul<256; Coul++) - { - if (!Exclude_color[Coul]) - { - Delta_R=(int)Principal_Palette[Coul].R-R; - Delta_V=(int)Principal_Palette[Coul].V-V; - Delta_B=(int)Principal_Palette[Coul].B-B; - - if (!(Dist=(Delta_R*Delta_R*30)+(Delta_V*Delta_V*59)+(Delta_B*Delta_B*11))) - return Coul; - - if (Dist>3)*Menu_Taille_couleur)*Menu_Facteur_X; - Debut_Y=Menu_Ordonnee_avant_fenetre+((2+((Couleur&7)<<2))*Menu_Facteur_Y); - Fin_X=Debut_X+Largeur; - Fin_Y=Debut_Y+Hauteur; - - // On affiche le bloc en entier si on peut, sinon on le découpe autour - // de la fenêtre. - if ( (Debut_Y>=Coin_Y) || (Fin_X<=Fenetre_Pos_X) || (Debut_X>=Coin_X) ) - Block(Debut_X,Debut_Y,Largeur,Hauteur,Vraie_couleur); - else - { - - if (Debut_X>=Fenetre_Pos_X) - { - if ( (Fin_X>Coin_X) || (Fin_Y>Coin_Y) ) - { - if ( (Fin_X>Coin_X) && (Fin_Y>Coin_Y) ) - { - Block(Coin_X,Debut_Y,Fin_X-Coin_X,Coin_Y-Debut_Y,Vraie_couleur); - Block(Debut_X,Coin_Y,Largeur,Fin_Y-Coin_Y,Vraie_couleur); - } - else - { - if (Fin_Y>Coin_Y) - Block(Debut_X,Coin_Y,Largeur,Fin_Y-Coin_Y,Vraie_couleur); - else - Block(Coin_X,Debut_Y,Fin_X-Coin_X,Hauteur,Vraie_couleur); - } - } - } - else - { - if (Fin_XCoin_Y) - { - Block(Debut_X,Debut_Y,Fenetre_Pos_X-Debut_X,Coin_Y-Debut_Y,Vraie_couleur); - Block(Debut_X,Coin_Y,Largeur,Fin_Y-Coin_Y,Vraie_couleur); - } - else - Block(Debut_X,Debut_Y,Fenetre_Pos_X-Debut_X,Hauteur,Vraie_couleur); - } - else - { - if (Fin_Y>Coin_Y) - { - Block(Debut_X,Debut_Y,Fenetre_Pos_X-Debut_X,Coin_Y-Debut_Y,Vraie_couleur); - Block(Coin_X,Debut_Y,Fin_X-Coin_X,Coin_Y-Debut_Y,Vraie_couleur); - Block(Debut_X,Coin_Y,Largeur,Fin_Y-Coin_Y,Vraie_couleur); - } - else - { - Block(Debut_X,Debut_Y,Fenetre_Pos_X-Debut_X,Hauteur,Vraie_couleur); - Block(Coin_X,Debut_Y,Fin_X-Coin_X,Hauteur,Vraie_couleur); - } - } - } - } - { - // Affichage du bloc directement dans le "buffer de fond" de la fenetre. - // Cela permet au bloc de couleur d'apparaitre si on déplace la fenetre. - short Pos_X; - short Pos_Y; - short Deb_X; // besoin d'une variable signée - short Deb_Y; // besoin d'une variable signée - // Attention aux unités - Deb_X = ((short)Debut_X - (short)Fenetre_Pos_X); - Deb_Y = ((short)Debut_Y - (short)Fenetre_Pos_Y); - - for (Pos_Y=Deb_Y;Pos_Y<(Deb_Y+Hauteur)&&Pos_Y=0&&Pos_Y>=0) - Pixel_fond(Pos_X,Pos_Y,Vraie_couleur); - } - } - } - UpdateRect(LARGEUR_MENU*Menu_Facteur_X,Menu_Ordonnee_avant_fenetre,Largeur_ecran-(LARGEUR_MENU*Menu_Facteur_X),(HAUTEUR_MENU-9)*Menu_Facteur_Y); -} - - -void Remapper_ecran_apres_changement_couleurs_menu(void) -{ - short Indice; - byte Table_de_conversion[256]; - short Temp/*,Temp2*/; - - if ( (CM_Clair!=Old_Clair) || (CM_Fonce!=Old_Fonce) || (CM_Blanc!=Old_Blanc) || (CM_Noir !=Old_Noir ) - || (CM_Trans!=Old_Trans) ) - { - // Création de la table de conversion - for (Indice=0; Indice<256; Indice++) - Table_de_conversion[Indice]=Indice; - - Table_de_conversion[Old_Noir ]=CM_Noir; - Table_de_conversion[Old_Fonce]=CM_Fonce; - Table_de_conversion[Old_Clair]=CM_Clair; - Table_de_conversion[Old_Blanc]=CM_Blanc; - - // Remappage de l'écran - - Temp=Fenetre_Hauteur*Menu_Facteur_Y; - - Remap_screen(Fenetre_Pos_X, Fenetre_Pos_Y, - Fenetre_Largeur*Menu_Facteur_X, - (Fenetre_Pos_Y+Temp on BeOS or Haiku - return 10*1024*1024; - #else - struct sysinfo info; - sysinfo(&info); - return info.freeram*info.mem_unit; - #endif -} - - -// Transformer une liste de shade en deux tables de conversion -void Liste2tables(word * Liste,short Pas,byte Mode,byte * Table_inc,byte * Table_dec) -{ - int Indice; - int Premier; - int Dernier; - int Couleur; - int Temp; - - - // On initialise les deux tables de conversion en Identité - for (Indice=0;Indice<256;Indice++) - { - Table_inc[Indice]=Indice; - Table_dec[Indice]=Indice; - } - - // On s'apprête à examiner l'ensemble de la liste - for (Indice=0;Indice<512;Indice++) - { - // On recherche la première case de la liste non vide (et non inhibée) - while ((Indice<512) && (Liste[Indice]>255)) - Indice++; - - // On note la position de la première case de la séquence - Premier=Indice; - - // On recherche la position de la dernière case de la séquence - for (Dernier=Premier;Liste[Dernier+1]<256;Dernier++); - - // Pour toutes les cases non vides (et non inhibées) qui suivent - switch (Mode) - { - case MODE_SHADE_NORMAL : - for (;(Indice<512) && (Liste[Indice]<256);Indice++) - { // On met à jour les tables de conversion - Couleur=Liste[Indice]; - Table_inc[Couleur]=Liste[(Indice+Pas<=Dernier)?Indice+Pas:Dernier]; - Table_dec[Couleur]=Liste[(Indice-Pas>=Premier)?Indice-Pas:Premier]; - } - break; - case MODE_SHADE_BOUCLE : - Temp=1+Dernier-Premier; - for (;(Indice<512) && (Liste[Indice]<256);Indice++) - { // On met à jour les tables de conversion - Couleur=Liste[Indice]; - Table_inc[Couleur]=Liste[Premier+((Pas+Indice-Premier)%Temp)]; - Table_dec[Couleur]=Liste[Premier+(((Temp-Pas)+Indice-Premier)%Temp)]; - } - break; - default : // MODE_SHADE_NOSAT - for (;(Indice<512) && (Liste[Indice]<256);Indice++) - { // On met à jour les tables de conversion - Couleur=Liste[Indice]; - if (Indice+Pas<=Dernier) - Table_inc[Couleur]=Liste[Indice+Pas]; - if (Indice-Pas>=Premier) - Table_dec[Couleur]=Liste[Indice-Pas]; - } - } - } -} - - -// Transformer un nombre (entier naturel) en chaîne -void Num2str(dword Nombre,char * Chaine,byte Taille) -{ - int Indice; - - for (Indice=Taille-1;Indice>=0;Indice--) - { - Chaine[Indice]=(Nombre%10)+'0'; - Nombre/=10; - if (Nombre==0) - for (Indice--;Indice>=0;Indice--) - Chaine[Indice]=' '; - } - Chaine[Taille]='\0'; -} - -// Transformer une chaîne en un entier naturel (renvoie -1 si ch. invalide) -int Str2num(char * Chaine) -{ - int Valeur=0; - - for (;*Chaine;Chaine++) - { - if ( (*Chaine>='0') && (*Chaine<='9') ) - Valeur=(Valeur*10)+(*Chaine-'0'); - else - return -1; - } - return Valeur; -} - - -// Arrondir un nombre réel à la valeur entière la plus proche -short Round(float Valeur) -{ - short Temp=Valeur; - - if (Valeur>=0) - { if ((Valeur-Temp)>= 0.5) Temp++; } - else - { if ((Valeur-Temp)<=-0.5) Temp--; } - - return Temp; -} - -// Arrondir le résultat d'une division à la valeur entière supérieure -short Round_div_max(short Numerateur,short Diviseur) -{ - if (!(Numerateur % Diviseur)) - return (Numerateur/Diviseur); - else - return (Numerateur/Diviseur)+1; -} - -// Retourne le minimum entre deux nombres -int Min(int A,int B) -{ - return (AB)?A:B; -} void Transformer_point(short X, short Y, float cosA, float sinA, short * Xr, short * Yr) @@ -754,301 +163,6 @@ void Transformer_point(short X, short Y, float cosA, float sinA, -// -- Recadrer la partie non-zoomée de l'image par rapport à la partie zoomée -// lorsqu'on scrolle en mode Loupe -- -void Recadrer_ecran_par_rapport_au_zoom(void) -{ - // Centrage en X - if (Principal_Largeur_image>Principal_Split) - { - Principal_Decalage_X=Loupe_Decalage_X+(Loupe_Largeur>>1) - -(Principal_Split>>1); - if (Principal_Decalage_X<0) - Principal_Decalage_X=0; - else - if (Principal_Largeur_imageMenu_Ordonnee) - { - Principal_Decalage_Y=Loupe_Decalage_Y+(Loupe_Hauteur>>1) - -(Menu_Ordonnee>>1); - if (Principal_Decalage_Y<0) - Principal_Decalage_Y=0; - else - if (Principal_Hauteur_image>1)-X_theorique)/Loupe_Facteur)*Loupe_Facteur); - Principal_Split=Principal_X_Zoom-(Menu_Facteur_X*LARGEUR_BARRE_SPLIT); - - // Correction en cas de débordement sur la gauche - while (Principal_Split*(Loupe_Facteur+1)=X_theorique) - { - Principal_Split-=Loupe_Facteur; - Principal_X_Zoom-=Loupe_Facteur; - } -} - - - -// -------------------- Calcul des information de la loupe ------------------- -void Calculer_donnees_loupe(void) -/* - Après modification des données de la loupe, il faut recalculer les limites. -*/ -{ - Calculer_split(); - - Loupe_Largeur=(Largeur_ecran-Principal_X_Zoom)/Loupe_Facteur; - - Loupe_Hauteur=Menu_Ordonnee/Loupe_Facteur; - if (Menu_Ordonnee%Loupe_Facteur) - Loupe_Hauteur++; - - if (Loupe_Mode && Loupe_Decalage_X) - { - if (Principal_Largeur_image=Principal_Hauteur_image) - Limite_Bas=Principal_Hauteur_image-1; - else - Limite_Bas=Limite_visible_Bas; - - if (Limite_visible_Droite>=Principal_Largeur_image) - Limite_Droite=Principal_Largeur_image-1; - else - Limite_Droite=Limite_visible_Droite; - - // -- Calcul des limites de la partie zoomée de l'image -- - Limite_Haut_Zoom =Loupe_Decalage_Y; - Limite_Gauche_Zoom=Loupe_Decalage_X; - Limite_visible_Bas_Zoom =Limite_Haut_Zoom+Loupe_Hauteur-1; - Limite_visible_Droite_Zoom=Limite_Gauche_Zoom+Loupe_Largeur-1; - - if (Limite_visible_Bas_Zoom>=Principal_Hauteur_image) - Limite_Bas_Zoom=Principal_Hauteur_image-1; - else - Limite_Bas_Zoom=Limite_visible_Bas_Zoom; - - if (Limite_visible_Droite_Zoom>=Principal_Largeur_image) - Limite_Droite_Zoom=Principal_Largeur_image-1; - else - Limite_Droite_Zoom=Limite_visible_Droite_Zoom; - } - else - { - // -- Calcul des limites de la partie visible de l'image -- - Limite_Haut =Principal_Decalage_Y; - Limite_Gauche=Principal_Decalage_X; - Limite_visible_Bas =Limite_Haut+(Menu_visible?Menu_Ordonnee:Hauteur_ecran)-1; // A REVOIR POUR SIMPLIFICATION - Limite_visible_Droite=Limite_Gauche+Largeur_ecran-1; - - if (Limite_visible_Bas>=Principal_Hauteur_image) - Limite_Bas=Principal_Hauteur_image-1; - else - Limite_Bas=Limite_visible_Bas; - - if (Limite_visible_Droite>=Principal_Largeur_image) - Limite_Droite=Principal_Largeur_image-1; - else - Limite_Droite=Limite_visible_Droite; - } -} - - -// -- Calculer les coordonnées du pinceau en fonction du snap et de la loupe - -void Calculer_coordonnees_pinceau(void) -{ - if ((Loupe_Mode) && (Mouse_X>=Principal_X_Zoom)) - { - Pinceau_X=((Mouse_X-Principal_X_Zoom)/Loupe_Facteur)+Loupe_Decalage_X; - Pinceau_Y=(Mouse_Y/Loupe_Facteur)+Loupe_Decalage_Y; - } - else - { - Pinceau_X=Mouse_X+Principal_Decalage_X; - Pinceau_Y=Mouse_Y+Principal_Decalage_Y; - } - - if (Snap_Mode) - { - Pinceau_X=(((Pinceau_X+(Snap_Largeur>>1)-Snap_Decalage_X)/Snap_Largeur)*Snap_Largeur)+Snap_Decalage_X; - Pinceau_Y=(((Pinceau_Y+(Snap_Hauteur>>1)-Snap_Decalage_Y)/Snap_Hauteur)*Snap_Hauteur)+Snap_Decalage_Y; - } -} - - -// ------------ Changer le facteur de zoom et tout mettre à jour ------------- -void Changer_facteur_loupe(byte Indice_facteur) -{ - short Centre_X; - short Centre_Y; - - Centre_X=Loupe_Decalage_X+(Loupe_Largeur>>1); - Centre_Y=Loupe_Decalage_Y+(Loupe_Hauteur>>1); - - Loupe_Facteur=FACTEUR_ZOOM[Indice_facteur]; - Table_mul_facteur_zoom=TABLE_ZOOM[Indice_facteur]; - Calculer_donnees_loupe(); - - if (Loupe_Mode) - { - // Recalculer le décalage de la loupe - // Centrage "brut" de lécran par rapport à la loupe - Loupe_Decalage_X=Centre_X-(Loupe_Largeur>>1); - Loupe_Decalage_Y=Centre_Y-(Loupe_Hauteur>>1); - // Correction en cas de débordement de l'image - if (Loupe_Decalage_X+Loupe_Largeur>Principal_Largeur_image) - Loupe_Decalage_X=Principal_Largeur_image-Loupe_Largeur; - if (Loupe_Decalage_Y+Loupe_Hauteur>Principal_Hauteur_image) - Loupe_Decalage_Y=Principal_Hauteur_image-Loupe_Hauteur; - if (Loupe_Decalage_X<0) - Loupe_Decalage_X=0; - if (Loupe_Decalage_Y<0) - Loupe_Decalage_Y=0; - - Recadrer_ecran_par_rapport_au_zoom(); - - Pixel_Preview=Pixel_Preview_Loupe; - - } - else - Pixel_Preview=Pixel_Preview_Normal; - - Calculer_limites(); - Calculer_coordonnees_pinceau(); -} - - -// -- Affichage de la limite de l'image ------------------------------------- -void Afficher_limites_de_l_image(void) -{ - short Debut; - short Pos; - short Fin; - byte Droite_visible; - byte Bas_visible; - short Ancienne_Limite_Zoom; - - Droite_visible=Principal_Largeur_image<((Loupe_Mode)?Principal_Split:Largeur_ecran); - Bas_visible =Principal_Hauteur_imagePrincipal_Largeur_image)?Largeur_ecran:Principal_Largeur_image)); - + Set_palette(Principal_Palette); if (!Fullscreen) @@ -1230,2392 +344,12 @@ void Initialiser_mode_video(int Largeur, int Hauteur, int Fullscreen) Calculer_donnees_loupe(); Calculer_limites(); Calculer_coordonnees_pinceau(); - + Resize_Largeur=0; Resize_Hauteur=0; } -// -- Interface avec l'image, affectée par le facteur de grossissement ------- - - // fonction d'affichage "Pixel" utilisée pour les opérations définitivement - // Ne doit à aucune condition être appelée en dehors de la partie visible - // de l'image dans l'écran (ça pourrait être grave) -void Afficher_pixel(word X,word Y,byte Couleur) - // X & Y sont la position d'un point dans l'IMAGE - // Couleur est la couleur du point - // Le Stencil est géré. - // Les effets sont gérés par appel à Fonction_effet(). - // La Loupe est gérée par appel à Pixel_Preview(). -{ - if ( ( (!Trame_Mode) || (Effet_Trame(X,Y)) ) - && (!((Stencil_Mode) && (Stencil[Lit_pixel_dans_ecran_courant(X,Y)]))) - && (!((Mask_Mode) && (Mask_table[Lit_pixel_dans_ecran_brouillon(X,Y)]))) ) - { - Couleur=Fonction_effet(X,Y,Couleur); - Pixel_dans_ecran_courant(X,Y,Couleur); - Pixel_Preview(X,Y,Couleur); - } -} - - -// -- Interface avec le menu et les fenêtres --------------------------------- - - // Affichage d'un pixel dans le menu (le menu doît être visible) - -void Pixel_dans_barre_d_outil(word X,word Y,byte Couleur) -{ - Block(X*Menu_Facteur_X,(Y*Menu_Facteur_Y)+Menu_Ordonnee,Menu_Facteur_X,Menu_Facteur_Y,Couleur); -} - - // Affichage d'un pixel dans la fenêtre (la fenêtre doît être visible) - -void Pixel_dans_fenetre(word X,word Y,byte Couleur) -{ - Block((X*Menu_Facteur_X)+Fenetre_Pos_X,(Y*Menu_Facteur_Y)+Fenetre_Pos_Y,Menu_Facteur_X,Menu_Facteur_Y,Couleur); -} - - -// -- Affichages de différents cadres dans une fenêtre ----------------------- - - // -- Cadre général avec couleurs paramètrables -- - -void Fenetre_Afficher_cadre_general(word Pos_X,word Pos_Y,word Largeur,word Hauteur, - byte Couleur_HG,byte Couleur_BD,byte Couleur_S,byte Couleur_CHG,byte Couleur_CBD) -// Paramètres de couleurs: -// Couleur_HG =Bords Haut et Gauche -// Couleur_BD =Bords Bas et Droite -// Couleur_S =Coins Haut-Droite et Bas-Gauche -// Couleur_CHG=Coin Haut-Gauche -// Couleur_CBD=Coin Bas-Droite -{ - // Bord haut (sans les extrémités) - Block(Fenetre_Pos_X+((Pos_X+1)*Menu_Facteur_X), - Fenetre_Pos_Y+(Pos_Y*Menu_Facteur_Y), - (Largeur-2)*Menu_Facteur_X,Menu_Facteur_Y,Couleur_HG); - - // Bord bas (sans les extrémités) - Block(Fenetre_Pos_X+((Pos_X+1)*Menu_Facteur_X), - Fenetre_Pos_Y+((Pos_Y+Hauteur-1)*Menu_Facteur_Y), - (Largeur-2)*Menu_Facteur_X,Menu_Facteur_Y,Couleur_BD); - - // Bord gauche (sans les extrémités) - Block(Fenetre_Pos_X+(Pos_X*Menu_Facteur_X), - Fenetre_Pos_Y+((Pos_Y+1)*Menu_Facteur_Y), - Menu_Facteur_X,(Hauteur-2)*Menu_Facteur_Y,Couleur_HG); - - // Bord droite (sans les extrémités) - Block(Fenetre_Pos_X+((Pos_X+Largeur-1)*Menu_Facteur_X), - Fenetre_Pos_Y+((Pos_Y+1)*Menu_Facteur_Y), - Menu_Facteur_X,(Hauteur-2)*Menu_Facteur_Y,Couleur_BD); - - // Coin haut gauche - Pixel_dans_fenetre(Pos_X,Pos_Y,Couleur_CHG); - // Coin haut droite - Pixel_dans_fenetre(Pos_X+Largeur-1,Pos_Y,Couleur_S); - // Coin bas droite - Pixel_dans_fenetre(Pos_X+Largeur-1,Pos_Y+Hauteur-1,Couleur_CBD); - // Coin bas gauche - Pixel_dans_fenetre(Pos_X,Pos_Y+Hauteur-1,Couleur_S); -} - - // -- Cadre dont tout le contour est d'une seule couleur -- - -void Fenetre_Afficher_cadre_mono(word Pos_X,word Pos_Y,word Largeur,word Hauteur,byte Couleur) -{ - Fenetre_Afficher_cadre_general(Pos_X,Pos_Y,Largeur,Hauteur,Couleur,Couleur,Couleur,Couleur,Couleur); -} - - // -- Cadre creux: foncé en haut-gauche et clair en bas-droite -- - -void Fenetre_Afficher_cadre_creux(word Pos_X,word Pos_Y,word Largeur,word Hauteur) -{ - Fenetre_Afficher_cadre_general(Pos_X,Pos_Y,Largeur,Hauteur,CM_Fonce,CM_Blanc,CM_Clair,CM_Fonce,CM_Blanc); -} - - // -- Cadre bombé: clair en haut-gauche et foncé en bas-droite -- - -void Fenetre_Afficher_cadre_bombe(word Pos_X,word Pos_Y,word Largeur,word Hauteur) -{ - Fenetre_Afficher_cadre_general(Pos_X,Pos_Y,Largeur,Hauteur,CM_Blanc,CM_Fonce,CM_Clair,CM_Blanc,CM_Fonce); -} - - // -- Cadre de séparation: un cadre bombé dans un cadre creux (3D!!!) -- - -void Fenetre_Afficher_cadre(word Pos_X,word Pos_Y,word Largeur,word Hauteur) -{ - Fenetre_Afficher_cadre_creux(Pos_X,Pos_Y,Largeur,Hauteur); - Fenetre_Afficher_cadre_bombe(Pos_X+1,Pos_Y+1,Largeur-2,Hauteur-2); -} - - -//-- Affichages relatifs à la palette dans le menu --------------------------- - - // -- Affichage des couleurs courante (fore/back) de pinceau dans le menu -- - -void Afficher_foreback(void) -{ - if (Menu_visible) - { - Block((LARGEUR_MENU-17)*Menu_Facteur_X,Menu_Ordonnee+Menu_Facteur_Y,Menu_Facteur_X<<4,Menu_Facteur_Y*7,Back_color); - Block((LARGEUR_MENU-13)*Menu_Facteur_X,Menu_Ordonnee+(Menu_Facteur_Y<<1),Menu_Facteur_X<<3,Menu_Facteur_Y*5,Fore_color); - - UpdateRect((LARGEUR_MENU-17)*Menu_Facteur_X,Menu_Ordonnee+Menu_Facteur_Y,Menu_Facteur_X<<4,Menu_Facteur_Y*7); - } -} - - // -- Tracer un cadre de couleur autour de la Fore_color dans le menu -- - -void Encadrer_couleur_menu(byte Couleur) -{ - word Debut_X,Debut_Y,Fin_X,Fin_Y; - word Indice; - - if ((Fore_color>=Couleur_debut_palette) && (Fore_color>3)*Menu_Taille_couleur)*Menu_Facteur_X; - Debut_Y=Menu_Ordonnee+((1+(((Fore_color-Couleur_debut_palette)&7)<<2))*Menu_Facteur_Y); - - Block(Debut_X,Debut_Y,(Menu_Taille_couleur+1)*Menu_Facteur_X,Menu_Facteur_Y,Couleur); - Block(Debut_X,Debut_Y+(Menu_Facteur_Y<<2),(Menu_Taille_couleur+1)*Menu_Facteur_X,Menu_Facteur_Y,Couleur); - - Block(Debut_X,Debut_Y+Menu_Facteur_Y,Menu_Facteur_X,Menu_Facteur_Y*3,Couleur); - Block(Debut_X+(Menu_Taille_couleur*Menu_Facteur_X),Debut_Y+Menu_Facteur_Y,Menu_Facteur_X,Menu_Facteur_Y*3,Couleur); - } - else - { - if (Couleur==CM_Noir) - { - Debut_X=(LARGEUR_MENU+1+((Fore_color-Couleur_debut_palette)>>3)*Menu_Taille_couleur)*Menu_Facteur_X; - Debut_Y=Menu_Ordonnee+((2+(((Fore_color-Couleur_debut_palette)&7)<<2))*Menu_Facteur_Y); - - Block(Debut_X,Debut_Y,Menu_Taille_couleur*Menu_Facteur_X, - Menu_Facteur_Y<<2,Fore_color); - - UpdateRect(Debut_X,Debut_Y,Menu_Taille_couleur*Menu_Facteur_X,Menu_Facteur_Y*4); // TODO On met à jour toute la palette... peut mieux faire - } - else - { - Debut_X=LARGEUR_MENU+1+((Fore_color-Couleur_debut_palette)>>3)*Menu_Taille_couleur; - Debut_Y=2+(((Fore_color-Couleur_debut_palette)&7)<<2); - - Fin_X=Debut_X+Menu_Taille_couleur-1; - Fin_Y=Debut_Y+3; - - for (Indice=Debut_X; Indice<=Fin_X; Indice++) - Block(Indice*Menu_Facteur_X,Menu_Ordonnee+(Debut_Y*Menu_Facteur_Y), - Menu_Facteur_X,Menu_Facteur_Y, - ((Indice+Debut_Y)&1)?CM_Blanc:CM_Noir); - - for (Indice=Debut_Y+1; Indice>3)*Menu_Taille_couleur)*Menu_Facteur_X, - Menu_Ordonnee+((2+((Couleur&7)<<2))*Menu_Facteur_Y), - (Menu_Taille_couleur-1)*Menu_Facteur_X, - Menu_Facteur_Y*3, - Couleur_debut_palette+Couleur); - else - for (Couleur=0;Couleur<64;Couleur++) - Block((LARGEUR_MENU+1+(Couleur>>3)*Menu_Taille_couleur)*Menu_Facteur_X, - Menu_Ordonnee+((2+((Couleur&7)<<2))*Menu_Facteur_Y), - Menu_Taille_couleur*Menu_Facteur_X, - Menu_Facteur_Y<<2, - Couleur_debut_palette+Couleur); - - Encadrer_couleur_menu(CM_Blanc); - UpdateRect(LARGEUR_MENU*Menu_Facteur_X,Menu_Ordonnee,Largeur_ecran-(LARGEUR_MENU*Menu_Facteur_X),(HAUTEUR_MENU-9)*Menu_Facteur_Y); - } -} - - // -- Recalculer l'origine de la palette dans le menu pour rendre la - // Fore_color visible -- - -void Recadrer_palette(void) -{ - byte Ancienne_couleur=Couleur_debut_palette; - - if (Fore_color=Couleur_debut_palette+64) - Couleur_debut_palette+=8; - } - if (Ancienne_couleur!=Couleur_debut_palette) - Afficher_palette_du_menu(); -} - - - // -- Afficher la barre de séparation entre les parties zoomées ou non en - // mode Loupe -- - -void Afficher_barre_de_split(void) -{ - // Partie grise du milieu - Block(Principal_Split+(Menu_Facteur_X<<1),Menu_Facteur_Y, - (LARGEUR_BARRE_SPLIT-4)*Menu_Facteur_X, - Menu_Ordonnee-(Menu_Facteur_Y<<1),CM_Clair); - - // Barre noire de gauche - Block(Principal_Split,0,Menu_Facteur_X,Menu_Ordonnee,CM_Noir); - - // Barre noire de droite - Block(Principal_X_Zoom-Menu_Facteur_X,0,Menu_Facteur_X,Menu_Ordonnee,CM_Noir); - - // Bord haut (blanc) - Block(Principal_Split+Menu_Facteur_X,0, - (LARGEUR_BARRE_SPLIT-3)*Menu_Facteur_X,Menu_Facteur_Y,CM_Blanc); - - // Bord gauche (blanc) - Block(Principal_Split+Menu_Facteur_X,Menu_Facteur_Y, - Menu_Facteur_X,(Menu_Ordonnee-(Menu_Facteur_Y<<1)),CM_Blanc); - - // Bord droite (gris foncé) - Block(Principal_X_Zoom-(Menu_Facteur_X<<1),Menu_Facteur_Y, - Menu_Facteur_X,(Menu_Ordonnee-(Menu_Facteur_Y<<1)),CM_Fonce); - - // Bord bas (gris foncé) - Block(Principal_Split+(Menu_Facteur_X<<1),Menu_Ordonnee-Menu_Facteur_Y, - (LARGEUR_BARRE_SPLIT-3)*Menu_Facteur_X,Menu_Facteur_Y,CM_Fonce); - - // Coin bas gauche - Block(Principal_Split+Menu_Facteur_X,Menu_Ordonnee-Menu_Facteur_Y, - Menu_Facteur_X,Menu_Facteur_Y,CM_Clair); - // Coin haut droite - Block(Principal_X_Zoom-(Menu_Facteur_X<<1),0, - Menu_Facteur_X,Menu_Facteur_Y,CM_Clair); - - UpdateRect(Principal_Split,0,LARGEUR_BARRE_SPLIT*Menu_Facteur_X,Menu_Ordonnee); // On réaffiche toute la partie à gauche du split, ce qui permet d'effacer son ancienne position -} - - // -- Afficher tout le menu -- - -void Afficher_menu(void) -{ - word Pos_X; - word Pos_Y; - char Chaine[4]; - - - if (Menu_visible) - { - // Affichage du sprite du menu - for (Pos_Y=0;Pos_Y=Principal_X_Zoom) )) - { - if ( (Operation_en_cours!=OPERATION_PIPETTE) - && (Operation_en_cours!=OPERATION_REMPLACER) ) - Print_dans_menu("X: Y: ",0); - else - { - Print_dans_menu("X: Y: ( )",0); - Num2str(Pipette_Couleur,Chaine,3); - Print_dans_menu(Chaine,20); - Print_general(170*Menu_Facteur_X,Menu_Ordonnee_Texte," ",0,Pipette_Couleur); - } - Print_coordonnees(); - } - Print_nom_fichier(); - } - UpdateRect(0,Menu_Ordonnee,Largeur_ecran,HAUTEUR_MENU*Menu_Facteur_Y); // on met toute la largur à jour, ça inclut la palette et la zone d'étant avec le nom du fichier - } -} - -// -- Affichage de texte ----------------------------------------------------- - - // -- Afficher une chaîne n'importe où à l'écran -- - -void Print_general(short X,short Y,char * Chaine,byte Couleur_texte,byte Couleur_fond) -{ - word Indice; - int Pos_X; - int Pos_Y; - byte *Caractere; - short Reel_X; - short Reel_Y; - byte Repeat_Menu_Facteur_X; - byte Repeat_Menu_Facteur_Y; - - Reel_Y=Y; - for (Pos_Y=0;Pos_Y<8;Pos_Y++) - { - Reel_X=0; // Position dans le buffer - for (Indice=0;Chaine[Indice]!='\0';Indice++) - { - // Pointeur sur le premier pixel du caractère - Caractere=Fonte+(((unsigned char)Chaine[Indice])<<6); - for (Pos_X=0;Pos_X<8<<3;Pos_X+=1<<3) - for (Repeat_Menu_Facteur_X=0;Repeat_Menu_Facteur_X Taille) - { - Chaine_affichee[Taille-1]=CARACTERE_SUSPENSION; - } - Print_dans_fenetre(X, Y, Chaine_affichee, Couleur_texte, Couleur_fond); -} - - // -- Afficher une chaîne dans une fenêtre -- - -void Print_dans_fenetre(short X,short Y,char * Chaine,byte Couleur_texte,byte Couleur_fond) -{ - Print_general((X*Menu_Facteur_X)+Fenetre_Pos_X, - (Y*Menu_Facteur_Y)+Fenetre_Pos_Y, - Chaine,Couleur_texte,Couleur_fond); - UpdateRect(X*Menu_Facteur_X+Fenetre_Pos_X,Y*Menu_Facteur_Y+Fenetre_Pos_Y,8*Menu_Facteur_X*strlen(Chaine),8*Menu_Facteur_Y); -} - - // -- Afficher une chaîne dans le menu -- - -void Print_dans_menu(char * Chaine, short Position) -{ - Print_general((18+(Position<<3))*Menu_Facteur_X,Menu_Ordonnee_Texte,Chaine,CM_Noir,CM_Clair); - UpdateRect((18+(Position<<3))*Menu_Facteur_X,Menu_Ordonnee_Texte,strlen(Chaine)*8*Menu_Facteur_X,8*Menu_Facteur_Y); -} - - // -- Afficher les coordonnées du pinceau dans le menu -- - -// Note : cette fonction n'affiche que les chiffres, pas les X: Y: qui sont dans la gestion principale, car elle est apellée très souvent. -void Print_coordonnees(void) -{ - char Tempo[5]; - - if (Menu_visible) - { - if ( (Operation_en_cours==OPERATION_PIPETTE) - || (Operation_en_cours==OPERATION_REMPLACER) ) - { - if ( (Pinceau_X>=0) && (Pinceau_Y>=0) - && (Pinceau_X12) - { - Nom_affiche[11]=CARACTERE_SUSPENSION; - Taille_nom = 12; - } - - Block((LARGEUR_MENU+2+((Menu_Taille_couleur-12)<<3))*Menu_Facteur_X, - Menu_Ordonnee_Texte,Menu_Facteur_X*96,Menu_Facteur_Y<<3,CM_Clair); - - Debut_X=LARGEUR_MENU+2+((Menu_Taille_couleur-Taille_nom)<<3); - - Print_general(Debut_X*Menu_Facteur_X,Menu_Ordonnee_Texte,Nom_affiche,CM_Noir,CM_Clair); - } -} - -// Fonction d'affichage d'une chaine numérique avec une fonte très fine -// Spécialisée pour les compteurs RGB -void Print_compteur(short X,short Y,char * Chaine,byte Couleur_texte,byte Couleur_fond) -{ - // Macros pour écrire des litteraux binaires. - // Ex: Ob(11110000) == 0xF0 - #define Ob(x) ((unsigned)Ob_(0 ## x ## uL)) - #define Ob_(x) ((x & 1) | (x >> 2 & 2) | (x >> 4 & 4) | (x >> 6 & 8) | \ - (x >> 8 & 16) | (x >> 10 & 32) | (x >> 12 & 64) | (x >> 14 & 128)) - - byte Caractere[14][8] = { - { // 0 - Ob(00011100), - Ob(00110110), - Ob(00110110), - Ob(00110110), - Ob(00110110), - Ob(00110110), - Ob(00110110), - Ob(00011100) - }, - { // 1 - Ob(00001100), - Ob(00011100), - Ob(00111100), - Ob(00001100), - Ob(00001100), - Ob(00001100), - Ob(00001100), - Ob(00001100) - }, - { // 2 - Ob(00011100), - Ob(00110110), - Ob(00000110), - Ob(00000110), - Ob(00000110), - Ob(00001100), - Ob(00011000), - Ob(00111110) - }, - { // 3 - Ob(00011100), - Ob(00110110), - Ob(00000110), - Ob(00001100), - Ob(00000110), - Ob(00000110), - Ob(00110110), - Ob(00011100) - }, - { // 4 - Ob(00001100), - Ob(00001100), - Ob(00011000), - Ob(00011000), - Ob(00110000), - Ob(00110100), - Ob(00111110), - Ob(00000100) - }, - { // 5 - Ob(00111110), - Ob(00110000), - Ob(00110000), - Ob(00111100), - Ob(00000110), - Ob(00000110), - Ob(00110110), - Ob(00011100) - }, - { // 6 - Ob(00011100), - Ob(00110110), - Ob(00110000), - Ob(00111100), - Ob(00110110), - Ob(00110110), - Ob(00110110), - Ob(00011100) - }, - { // 7 - Ob(00111110), - Ob(00000110), - Ob(00000110), - Ob(00001100), - Ob(00011000), - Ob(00011000), - Ob(00011000), - Ob(00011000) - }, - { // 8 - Ob(00011100), - Ob(00110110), - Ob(00110110), - Ob(00011100), - Ob(00110110), - Ob(00110110), - Ob(00110110), - Ob(00011100) - }, - { // 9 - Ob(00011100), - Ob(00110110), - Ob(00110110), - Ob(00011110), - Ob(00000110), - Ob(00000110), - Ob(00110110), - Ob(00011100) - }, - { // (espace) - Ob(00000000), - Ob(00000000), - Ob(00000000), - Ob(00000000), - Ob(00000000), - Ob(00000000), - Ob(00000000), - Ob(00000000) - }, - { // + - Ob(00000000), - Ob(00001000), - Ob(00001000), - Ob(00111110), - Ob(00001000), - Ob(00001000), - Ob(00000000), - Ob(00000000) - }, - { // - - Ob(00000000), - Ob(00000000), - Ob(00000000), - Ob(00111110), - Ob(00000000), - Ob(00000000), - Ob(00000000), - Ob(00000000) - }, - { // +- - Ob(00001000), - Ob(00001000), - Ob(00111110), - Ob(00001000), - Ob(00001000), - Ob(00000000), - Ob(00111110), - Ob(00000000) - } }; - - word Indice; - short Pos_X; - short Pos_Y; - for (Indice=0;Chaine[Indice]!='\0';Indice++) - { - int Numero_car; - switch(Chaine[Indice]) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - Numero_car=Chaine[Indice]-'0'; - break; - case ' ': - default: - Numero_car=10; - break; - case '+': - Numero_car=11; - break; - case '-': - Numero_car=12; - break; - case '±': - Numero_car=13; - break; - } - for (Pos_Y=0;Pos_Y<8;Pos_Y++) - { - for (Pos_X=0;Pos_X<6;Pos_X++) - { - byte Couleur = (Caractere[Numero_car][Pos_Y] & (1 << (6-Pos_X))) ? Couleur_texte:Couleur_fond; - Pixel_dans_fenetre(X+(Indice*6+Pos_X),Y+Pos_Y,Couleur); - } - } - } - UpdateRect(Fenetre_Pos_X+X*Menu_Facteur_X,Fenetre_Pos_Y+Y*Menu_Facteur_Y,strlen(Chaine)*Menu_Facteur_X*6,8*Menu_Facteur_Y); -} - -// -- Calcul des différents effets ------------------------------------------- - - // -- Aucun effet en cours -- - -byte Aucun_effet(__attribute__((unused)) word X,__attribute__((unused)) word Y,byte Couleur) -{ - return Couleur; -} - - // -- Effet de Shading -- - -byte Effet_Shade(word X,word Y,__attribute__((unused)) byte Couleur) -{ - return Shade_Table[Lit_pixel_dans_ecran_feedback(X,Y)]; -} - -byte Effet_Quick_shade(word X,word Y,byte Couleur) -{ - int C=Couleur=Lit_pixel_dans_ecran_feedback(X,Y); - int Sens=(Fore_color<=Back_color); - byte Debut,Fin; - int Largeur; - - if (Sens) - { - Debut=Fore_color; - Fin =Back_color; - } - else - { - Debut=Back_color; - Fin =Fore_color; - } - - if ((C>=Debut) && (C<=Fin) && (Debut!=Fin)) - { - Largeur=1+Fin-Debut; - - if ( ((Mouse_K==A_GAUCHE) && Sens) || ((Mouse_K==A_DROITE) && (!Sens)) ) - C-=Quick_shade_Step%Largeur; - else - C+=Quick_shade_Step%Largeur; - - if (CFin) - switch (Quick_shade_Loop) - { - case MODE_SHADE_NORMAL : return Fin; - case MODE_SHADE_BOUCLE : return (C-Largeur); - default : return Couleur; - } - } - - return C; -} - - // -- Effet de Tiling -- - -byte Effet_Tiling(word X,word Y,__attribute__((unused)) byte Couleur) -{ - return Lit_pixel_dans_brosse((X+Brosse_Largeur-Tiling_Decalage_X)%Brosse_Largeur, - (Y+Brosse_Hauteur-Tiling_Decalage_Y)%Brosse_Hauteur); -} - - // -- Effet de Smooth -- - -byte Effet_Smooth(word X,word Y,__attribute__((unused)) byte Couleur) -{ - int R,V,B; - byte C; - int Poids,Poids_total; - byte X2=((X+1)(Limite_Droite+1)) - { - (*Largeur)=(Limite_Droite-(*X))+1; - } - - if ((*Y)(Limite_Bas+1)) - { - (*Hauteur)=(Limite_Bas-(*Y))+1; - } -} - - // -- Calcul de redimensionnement du pinceau pour éviter les débordements - // de l'écran zoomé et de l'image -- - -void Calculer_dimensions_clipees_zoom(short * X,short * Y,short * Largeur,short * Hauteur) -{ - if ((*X)(Limite_Droite_Zoom+1)) - { - (*Largeur)=(Limite_Droite_Zoom-(*X))+1; - } - - if ((*Y)(Limite_Bas_Zoom+1)) - { - (*Hauteur)=(Limite_Bas_Zoom-(*Y))+1; - } -} - - - // -- Afficher le pinceau (de façon définitive ou non) -- - -void Afficher_pinceau(short X,short Y,byte Couleur,byte Preview) - // X,Y: position du centre du pinceau - // Couleur: couleur à appliquer au pinceau - // Preview: "Il ne faut l'afficher qu'à l'écran" -{ - short Debut_X; // Position X (dans l'image) à partir de laquelle on - // affiche la brosse/pinceau - short Debut_Y; // Position Y (dans l'image) à partir de laquelle on - // affiche la brosse/pinceau - short Largeur; // Largeur dans l'écran selon laquelle on affiche la - // brosse/pinceau - short Hauteur; // Hauteur dans l'écran selon laquelle on affiche la - // brosse/pinceau - short Debut_Compteur_X; // Position X (dans la brosse/pinceau) à partir - // de laquelle on affiche la brosse/pinceau - short Debut_Compteur_Y; // Position Y (dans la brosse/pinceau) à partir - // de laquelle on affiche la brosse/pinceau - short Pos_X; // Position X (dans l'image) en cours d'affichage - short Pos_Y; // Position Y (dans l'image) en cours d'affichage - short Compteur_X; // Position X (dans la brosse/pinceau) en cours - // d'affichage - short Compteur_Y; // Position Y (dans la brosse/pinceau) en cours - // d'affichage - short Fin_Compteur_X; // Position X ou s'arrête l'affichade de la - // brosse/pinceau - short Fin_Compteur_Y; // Position Y ou s'arrête l'affichade de la - // brosse/pinceau - byte Couleur_temporaire; // Couleur de la brosse en cours d'affichage - int Position; - byte * Temp; - - if (!(Preview && Mouse_K)) // Si bouton enfoncé & preview > pas de dessin - switch (Pinceau_Forme) - { - case FORME_PINCEAU_POINT : // !!! TOUJOURS EN PREVIEW !!! - if ( (Pinceau_X>=Limite_Gauche) - && (Pinceau_X<=Limite_Droite) - && (Pinceau_Y>=Limite_Haut) - && (Pinceau_Y<=Limite_Bas) ) - { - Pixel_Preview(Pinceau_X,Pinceau_Y,Couleur); - Mettre_Ecran_A_Jour(X,Y,1,1); - } - break; - - case FORME_PINCEAU_BROSSE_COULEUR : // Brosse en couleur - - Debut_X=X-Brosse_Decalage_X; - Debut_Y=Y-Brosse_Decalage_Y; - Largeur=Brosse_Largeur; - Hauteur=Brosse_Hauteur; - Calculer_dimensions_clipees(&Debut_X,&Debut_Y,&Largeur,&Hauteur); - if (Largeur<=0 || Hauteur<=0) - break; - Debut_Compteur_X=Debut_X-(X-Brosse_Decalage_X); - Debut_Compteur_Y=Debut_Y-(Y-Brosse_Decalage_Y); - Fin_Compteur_X=Debut_Compteur_X+Largeur; - Fin_Compteur_Y=Debut_Compteur_Y+Hauteur; - - if (Preview) - { - if ( (Largeur>0) && (Hauteur>0) ) - Display_brush_Color( - Debut_X-Principal_Decalage_X, - Debut_Y-Principal_Decalage_Y, - Debut_Compteur_X, - Debut_Compteur_Y, - Largeur, - Hauteur, - Back_color, - Brosse_Largeur - ); - - if (Loupe_Mode) - { - Calculer_dimensions_clipees_zoom(&Debut_X,&Debut_Y,&Largeur, - &Hauteur - ); - - Debut_Compteur_X=Debut_X-(X-Brosse_Decalage_X); - Debut_Compteur_Y=Debut_Y-(Y-Brosse_Decalage_Y); - - if ( (Largeur>0) && (Hauteur>0) ) - { - // Corrections dues au Zoom: - Debut_X=(Debut_X-Loupe_Decalage_X)*Loupe_Facteur; - Debut_Y=(Debut_Y-Loupe_Decalage_Y)*Loupe_Facteur; - Hauteur=Debut_Y+(Hauteur*Loupe_Facteur); - if (Hauteur>Menu_Ordonnee) - Hauteur=Menu_Ordonnee; - - Display_brush_Color_zoom(Principal_X_Zoom+Debut_X,Debut_Y, - Debut_Compteur_X,Debut_Compteur_Y, - Largeur,Hauteur,Back_color, - Brosse_Largeur, - Buffer_de_ligne_horizontale); - } - } - - Mettre_Ecran_A_Jour(X-Brosse_Decalage_X,Y-Brosse_Decalage_Y,Brosse_Largeur,Brosse_Hauteur); - - } - else - { - if ((Smear_Mode) && (Shade_Table==Shade_Table_gauche)) - { - if (Smear_Debut) - { - if ((Largeur>0) && (Hauteur>0)) - { - Copier_une_partie_d_image_dans_une_autre( - Principal_Ecran, Debut_X, Debut_Y, Largeur, Hauteur, - Principal_Largeur_image, Smear_Brosse, - Debut_Compteur_X, Debut_Compteur_Y, - Smear_Brosse_Largeur - ); - Mettre_Ecran_A_Jour(Debut_X,Debut_Y,Largeur,Hauteur); - } - Smear_Debut=0; - } - else - { - for (Pos_Y = Debut_Y, Compteur_Y = Debut_Compteur_Y; - Compteur_Y < Fin_Compteur_Y; - Pos_Y++, Compteur_Y++ - ) - for (Pos_X = Debut_X, Compteur_X = Debut_Compteur_X; - Compteur_X < Fin_Compteur_X; - Pos_X++, Compteur_X++ - ) - { - Couleur_temporaire = Lit_pixel_dans_ecran_courant( - Pos_X,Pos_Y - ); - Position = (Compteur_Y * Smear_Brosse_Largeur)+ Compteur_X; - if ( (Lit_pixel_dans_brosse(Compteur_X,Compteur_Y) != Back_color) - && (Compteur_Y=Smear_Min_Y) && (Compteur_X>=Smear_Min_X) ) - Afficher_pixel(Pos_X,Pos_Y,Smear_Brosse[Position]); - Smear_Brosse[Position]=Couleur_temporaire; - } - - Mettre_Ecran_A_Jour(Debut_X,Debut_Y,Largeur,Hauteur); - } - - Smear_Min_X=Debut_Compteur_X; - Smear_Min_Y=Debut_Compteur_Y; - Smear_Max_X=Fin_Compteur_X; - Smear_Max_Y=Fin_Compteur_Y; - } - else - { - if (Shade_Table==Shade_Table_gauche) - for (Pos_Y=Debut_Y,Compteur_Y=Debut_Compteur_Y;Compteur_Y0) && (Hauteur>0) ) - Display_brush_Mono(Debut_X-Principal_Decalage_X, - Debut_Y-Principal_Decalage_Y, - Debut_Compteur_X,Debut_Compteur_Y, - Largeur,Hauteur, - Back_color,Fore_color, - Brosse_Largeur); - - if (Loupe_Mode) - { - Calculer_dimensions_clipees_zoom(&Debut_X,&Debut_Y,&Largeur,&Hauteur); - Debut_Compteur_X=Debut_X-(X-Brosse_Decalage_X); - Debut_Compteur_Y=Debut_Y-(Y-Brosse_Decalage_Y); - - if ( (Largeur>0) && (Hauteur>0) ) - { - // Corrections dues au Zoom: - Debut_X=(Debut_X-Loupe_Decalage_X)*Loupe_Facteur; - Debut_Y=(Debut_Y-Loupe_Decalage_Y)*Loupe_Facteur; - Hauteur=Debut_Y+(Hauteur*Loupe_Facteur); - if (Hauteur>Menu_Ordonnee) - Hauteur=Menu_Ordonnee; - - Display_brush_Mono_zoom(Principal_X_Zoom+Debut_X,Debut_Y, - Debut_Compteur_X,Debut_Compteur_Y, - Largeur,Hauteur, - Back_color,Fore_color, - Brosse_Largeur, - Buffer_de_ligne_horizontale); - - } - } - } - else - { - if ((Smear_Mode) && (Shade_Table==Shade_Table_gauche)) - { - if (Smear_Debut) - { - if ((Largeur>0) && (Hauteur>0)) - Copier_une_partie_d_image_dans_une_autre(Principal_Ecran, - Debut_X,Debut_Y, - Largeur,Hauteur, - Principal_Largeur_image, - Smear_Brosse, - Debut_Compteur_X, - Debut_Compteur_Y, - Smear_Brosse_Largeur); - //UPDATERECT - Smear_Debut=0; - } - else - { - for (Pos_Y=Debut_Y,Compteur_Y=Debut_Compteur_Y;Compteur_Y=Smear_Min_Y) && (Compteur_X>=Smear_Min_X) ) - Afficher_pixel(Pos_X,Pos_Y,Smear_Brosse[Position]); - Smear_Brosse[Position]=Couleur_temporaire; - } - - UpdateRect(Max(Debut_X,0),Max(Debut_Y,0), - Fin_Compteur_X,Fin_Compteur_Y - ); - - } - - Smear_Min_X=Debut_Compteur_X; - Smear_Min_Y=Debut_Compteur_Y; - Smear_Max_X=Fin_Compteur_X; - Smear_Max_Y=Fin_Compteur_Y; - } - else - { - for (Pos_Y=Debut_Y,Compteur_Y=Debut_Compteur_Y;Compteur_Y0) && (Hauteur>0) ) - Display_brush_Mono(Debut_X-Principal_Decalage_X, - Debut_Y-Principal_Decalage_Y, - Debut_Compteur_X,Debut_Compteur_Y, - Largeur,Hauteur, - 0,Fore_color, - TAILLE_MAXI_PINCEAU); - - if (Loupe_Mode) - { - Calculer_dimensions_clipees_zoom(&Debut_X,&Debut_Y,&Largeur,&Hauteur); - Debut_Compteur_X=Debut_X-(X-Pinceau_Decalage_X); - Debut_Compteur_Y=Debut_Y-(Y-Pinceau_Decalage_Y); - - if ( (Largeur>0) && (Hauteur>0) ) - { - // Corrections dues au Zoom: - Debut_X=(Debut_X-Loupe_Decalage_X)*Loupe_Facteur; - Debut_Y=(Debut_Y-Loupe_Decalage_Y)*Loupe_Facteur; - Hauteur=Debut_Y+(Hauteur*Loupe_Facteur); - if (Hauteur>Menu_Ordonnee) - Hauteur=Menu_Ordonnee; - - Display_brush_Mono_zoom(Principal_X_Zoom+Debut_X,Debut_Y, - Debut_Compteur_X,Debut_Compteur_Y, - Largeur,Hauteur, - 0,Fore_color, - TAILLE_MAXI_PINCEAU, - Buffer_de_ligne_horizontale); - - } - } - - Brosse=Temp; - } - else - { - if ((Smear_Mode) && (Shade_Table==Shade_Table_gauche)) - { - if (Smear_Debut) - { - if ((Largeur>0) && (Hauteur>0)) - Copier_une_partie_d_image_dans_une_autre(Principal_Ecran, - Debut_X,Debut_Y, - Largeur,Hauteur, - Principal_Largeur_image, - Smear_Brosse, - Debut_Compteur_X, - Debut_Compteur_Y, - Smear_Brosse_Largeur); - // UPDATERECT - Smear_Debut=0; - } - else - { - for (Pos_Y=Debut_Y,Compteur_Y=Debut_Compteur_Y;Compteur_Y=Smear_Min_Y) && (Compteur_X>=Smear_Min_X) ) - Afficher_pixel(Pos_X,Pos_Y,Smear_Brosse[Position]); - Smear_Brosse[Position]=Couleur_temporaire; - } - } - - UpdateRect(Debut_X,Debut_Y, - Fin_Compteur_X,Fin_Compteur_Y - ); - - Smear_Min_X=Debut_Compteur_X; - Smear_Min_Y=Debut_Compteur_Y; - Smear_Max_X=Fin_Compteur_X; - Smear_Max_Y=Fin_Compteur_Y; - } - else - { - for (Pos_Y=Debut_Y,Compteur_Y=Debut_Compteur_Y;Compteur_Y=Limite_Gauche) - && (Pinceau_X<=Limite_Droite) - && (Pinceau_Y>=Limite_Haut) - && (Pinceau_Y<=Limite_Bas) ) - { - Pixel_Preview(Pinceau_X,Pinceau_Y,Lit_pixel_dans_ecran_courant(Pinceau_X,Pinceau_Y)); - Mettre_Ecran_A_Jour(Pinceau_X,Pinceau_Y,1,1); - } - break; - case FORME_PINCEAU_BROSSE_COULEUR : // Brosse en couleur - case FORME_PINCEAU_BROSSE_MONOCHROME : // Brosse monochrome - Debut_X=X-Brosse_Decalage_X; - Debut_Y=Y-Brosse_Decalage_Y; - Largeur=Brosse_Largeur; - Hauteur=Brosse_Hauteur; - Calculer_dimensions_clipees(&Debut_X,&Debut_Y,&Largeur,&Hauteur); - Debut_Compteur_X=Debut_X-(X-Brosse_Decalage_X); - Debut_Compteur_Y=Debut_Y-(Y-Brosse_Decalage_Y); - Fin_Compteur_X=Debut_Compteur_X+Largeur; - Fin_Compteur_Y=Debut_Compteur_Y+Hauteur; - - if ( (Largeur>0) && (Hauteur>0) ) - Clear_brush(Debut_X-Principal_Decalage_X, - Debut_Y-Principal_Decalage_Y, - Debut_Compteur_X,Debut_Compteur_Y, - Largeur,Hauteur,Back_color, - Principal_Largeur_image); - - if (Loupe_Mode) - { - Calculer_dimensions_clipees_zoom(&Debut_X,&Debut_Y,&Largeur,&Hauteur); - Debut_Compteur_X=Debut_X; - Debut_Compteur_Y=Debut_Y; - - if ( (Largeur>0) && (Hauteur>0) ) - { - // Corrections dues au Zoom: - Debut_X=(Debut_X-Loupe_Decalage_X)*Loupe_Facteur; - Debut_Y=(Debut_Y-Loupe_Decalage_Y)*Loupe_Facteur; - Hauteur=Debut_Y+(Hauteur*Loupe_Facteur); - if (Hauteur>Menu_Ordonnee) - Hauteur=Menu_Ordonnee; - - Clear_brush_zoom(Principal_X_Zoom+Debut_X,Debut_Y, - Debut_Compteur_X,Debut_Compteur_Y, - Largeur,Hauteur,Back_color, - Principal_Largeur_image, - Buffer_de_ligne_horizontale); - } - } - break; - default: // Pinceau - Debut_X=X-Pinceau_Decalage_X; - Debut_Y=Y-Pinceau_Decalage_Y; - Largeur=Pinceau_Largeur; - Hauteur=Pinceau_Hauteur; - Calculer_dimensions_clipees(&Debut_X,&Debut_Y,&Largeur,&Hauteur); - Debut_Compteur_X=Debut_X-(X-Pinceau_Decalage_X); - Debut_Compteur_Y=Debut_Y-(Y-Pinceau_Decalage_Y); - Fin_Compteur_X=Debut_Compteur_X+Largeur; - Fin_Compteur_Y=Debut_Compteur_Y+Hauteur; - - Temp=Brosse; - Brosse=Pinceau_Sprite; - - if ( (Largeur>0) && (Hauteur>0) ) - { - Clear_brush(Debut_X-Principal_Decalage_X, - Debut_Y-Principal_Decalage_Y, - Debut_Compteur_X,Debut_Compteur_Y, - Largeur,Hauteur,0, - Principal_Largeur_image); - } - - if (Loupe_Mode) - { - Calculer_dimensions_clipees_zoom(&Debut_X,&Debut_Y,&Largeur,&Hauteur); - Debut_Compteur_X=Debut_X; - Debut_Compteur_Y=Debut_Y; - - if ( (Largeur>0) && (Hauteur>0) ) - { - // Corrections dues au Zoom: - Debut_X=(Debut_X-Loupe_Decalage_X)*Loupe_Facteur; - Debut_Y=(Debut_Y-Loupe_Decalage_Y)*Loupe_Facteur; - Hauteur=Debut_Y+(Hauteur*Loupe_Facteur); - if (Hauteur>Menu_Ordonnee) - Hauteur=Menu_Ordonnee; - - Clear_brush_zoom(Principal_X_Zoom+Debut_X,Debut_Y, - Debut_Compteur_X,Debut_Compteur_Y, - Largeur,Hauteur,0, - Principal_Largeur_image, - Buffer_de_ligne_horizontale); - } - } - - Brosse=Temp; - break; - } -} - - -// -- Fonctions de manipulation du curseur ----------------------------------- - - - // -- Afficher une barre horizontale XOR zoomée - -void Ligne_horizontale_XOR_Zoom(short Pos_X, short Pos_Y, short Largeur) -{ - short Pos_X_reelle=Principal_X_Zoom+(Pos_X-Loupe_Decalage_X)*Loupe_Facteur; - short Pos_Y_reelle=(Pos_Y-Loupe_Decalage_Y)*Loupe_Facteur; - short Largeur_reelle=Largeur*Loupe_Facteur; - short Pos_Y_Fin=(Pos_Y_reelle+Loupe_Facteur=Principal_X_Zoom) ) ) - || (Fenetre) || (Forme_curseur==FORME_CURSEUR_SABLIER) ) - Forme=Forme_curseur; - else - Forme=FORME_CURSEUR_FLECHE; - - switch(Forme) - { - case FORME_CURSEUR_CIBLE : - if (!Cacher_pinceau) - Afficher_pinceau(Pinceau_X,Pinceau_Y,Fore_color,1); - if (!Cacher_curseur) - { - if (Config.Curseur==1) - { - Debut_Y=(Mouse_Y<6)?6-Mouse_Y:0; - if (Debut_Y<4) - Ligne_verticale_XOR (Mouse_X,Mouse_Y+Debut_Y-6,4-Debut_Y); - - Debut_X=(Mouse_X<6)?(short)6-Mouse_X:0; - if (Debut_X<4) - Ligne_horizontale_XOR(Mouse_X+Debut_X-6,Mouse_Y,4-Debut_X); - - Fin_X=(Mouse_X+7>Largeur_ecran)?Mouse_X+7-Largeur_ecran:0; - if (Fin_X<4) - Ligne_horizontale_XOR(Mouse_X+3,Mouse_Y,4-Fin_X); - - Fin_Y=(Mouse_Y+7>Hauteur_ecran)?Mouse_Y+7-Hauteur_ecran:0; - if (Fin_Y<4) - Ligne_verticale_XOR (Mouse_X,Mouse_Y+3,4-Fin_Y); - - UpdateRect(Mouse_X+Debut_X-6,Mouse_Y+Debut_Y-6,12-Fin_X,12-Fin_Y); - } - else - { - Temp=(Config.Curseur)?FORME_CURSEUR_CIBLE_FINE:FORME_CURSEUR_CIBLE; - Debut_X=Mouse_X-Curseur_Decalage_X[Temp]; - Debut_Y=Mouse_Y-Curseur_Decalage_Y[Temp]; - - for (Pos_X=Debut_X,Compteur_X=0;Compteur_X<15;Pos_X++,Compteur_X++) - { - if( Pos_X < 0 ) continue; - for (Pos_Y=Debut_Y,Compteur_Y=0;Compteur_Y<15;Pos_Y++,Compteur_Y++) - { - if( Pos_Y < 0 ) continue; - Couleur=SPRITE_CURSEUR[Temp][Compteur_Y][Compteur_X]; - FOND_CURSEUR[Compteur_Y][Compteur_X]=Lit_pixel(Pos_X,Pos_Y); - if (Couleur!=CM_Trans) - Pixel(Pos_X,Pos_Y,Couleur); - if (Pos_Y > Hauteur_ecran) break; - } - if (Pos_X >= Largeur_ecran) break; - } - - UpdateRect(Max(Debut_X,0),Max(Debut_Y,0),Compteur_X,Compteur_Y); - } - } - break; - - case FORME_CURSEUR_CIBLE_PIPETTE: - if (!Cacher_pinceau) - Afficher_pinceau(Pinceau_X,Pinceau_Y,Fore_color,1); - if (!Cacher_curseur) - { - if (Config.Curseur==1) - { - // Barres formant la croix principale - - Debut_Y=(Mouse_Y<5)?5-Mouse_Y:0; - if (Debut_Y<3) - Ligne_verticale_XOR (Mouse_X,Mouse_Y+Debut_Y-5,3-Debut_Y); - - Debut_X=(Mouse_X<5)?(short)5-Mouse_X:0; - if (Debut_X<3) - Ligne_horizontale_XOR(Mouse_X+Debut_X-5,Mouse_Y,3-Debut_X); - - Fin_X=(Mouse_X+6>Largeur_ecran)?Mouse_X+6-Largeur_ecran:0; - if (Fin_X<3) - Ligne_horizontale_XOR(Mouse_X+3,Mouse_Y,3-Fin_X); - - Fin_Y=(Mouse_Y+6>Menu_Ordonnee/*Hauteur_ecran*/)?Mouse_Y+6-Menu_Ordonnee/*Hauteur_ecran*/:0; - if (Fin_Y<3) - Ligne_verticale_XOR (Mouse_X,Mouse_Y+3,3-Fin_Y); - - // Petites barres aux extrémités - - Debut_X=(!Mouse_X); - Debut_Y=(!Mouse_Y); - Fin_X=(Mouse_X>=Largeur_ecran-1); - Fin_Y=(Mouse_Y>=Menu_Ordonnee-1); - - if (Mouse_Y>5) - Ligne_horizontale_XOR(Debut_X+Mouse_X-1,Mouse_Y-6,3-(Debut_X+Fin_X)); - - if (Mouse_X>5) - Ligne_verticale_XOR (Mouse_X-6,Debut_Y+Mouse_Y-1,3-(Debut_Y+Fin_Y)); - - if (Mouse_X=0) && (Pos_X=0) && (Pos_Y=Largeur_ecran) break; - for (Pos_Y=Debut_Y,Compteur_Y=0;Compteur_Y<15;Pos_Y++,Compteur_Y++) - { - if(Pos_Y<0) continue; - if(Pos_Y>=Hauteur_ecran) break; - Couleur=SPRITE_CURSEUR[Forme][Compteur_Y][Compteur_X]; - // On sauvegarde dans FOND_CURSEUR pour restaurer plus tard - FOND_CURSEUR[Compteur_Y][Compteur_X]=Lit_pixel(Pos_X,Pos_Y); - if (Couleur!=CM_Trans) - Pixel(Pos_X,Pos_Y,Couleur); - } - } - UpdateRect(Max(Debut_X,0),Max(Debut_Y,0),Compteur_X,Compteur_Y); - break; - - case FORME_CURSEUR_CIBLE_XOR : - Pos_X=Pinceau_X-Principal_Decalage_X; - Pos_Y=Pinceau_Y-Principal_Decalage_Y; - - Compteur_X=(Loupe_Mode)?Principal_Split:Largeur_ecran; // Largeur de la barre XOR - if ((Pos_Y=Limite_Haut)) - { - Ligne_horizontale_XOR(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X); - UpdateRect(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X,1); - } - - if ((Pos_X=Limite_Gauche)) - { - Ligne_verticale_XOR(Pinceau_X-Principal_Decalage_X,0,Menu_Ordonnee); - UpdateRect(Pinceau_X-Principal_Decalage_X,0,1,Menu_Ordonnee); - } - - if (Loupe_Mode) - { - // UPDATERECT - if ((Pinceau_Y>=Limite_Haut_Zoom) && (Pinceau_Y<=Limite_visible_Bas_Zoom)) - Ligne_horizontale_XOR_Zoom(Limite_Gauche_Zoom,Pinceau_Y,Loupe_Largeur); - if ((Pinceau_X>=Limite_Gauche_Zoom) && (Pinceau_X<=Limite_visible_Droite_Zoom)) - Ligne_verticale_XOR_Zoom(Pinceau_X,Limite_Haut_Zoom,Loupe_Hauteur); - } - break; - case FORME_CURSEUR_RECTANGLE_XOR : - // !!! Cette forme ne peut pas être utilisée en mode Loupe !!! - - // Petite croix au centre - Debut_X=(Mouse_X-3); - Debut_Y=(Mouse_Y-3); - Fin_X =(Mouse_X+4); - Fin_Y =(Mouse_Y+4); - if (Debut_X<0) - Debut_X=0; - if (Debut_Y<0) - Debut_Y=0; - if (Fin_X>Largeur_ecran) - Fin_X=Largeur_ecran; - if (Fin_Y>Menu_Ordonnee) - Fin_Y=Menu_Ordonnee; - - Ligne_horizontale_XOR(Debut_X,Mouse_Y,Fin_X-Debut_X); - Ligne_verticale_XOR (Mouse_X,Debut_Y,Fin_Y-Debut_Y); - - // Grand rectangle autour - Debut_X=Mouse_X-(Loupe_Largeur>>1); - Debut_Y=Mouse_Y-(Loupe_Hauteur>>1); - if (Debut_X+Loupe_Largeur>=Limite_Droite-Principal_Decalage_X) - Debut_X=Limite_Droite-Loupe_Largeur-Principal_Decalage_X+1; - if (Debut_Y+Loupe_Hauteur>=Limite_Bas-Principal_Decalage_Y) - Debut_Y=Limite_Bas-Loupe_Hauteur-Principal_Decalage_Y+1; - if (Debut_X<0) - Debut_X=0; - if (Debut_Y<0) - Debut_Y=0; - Fin_X=Debut_X+Loupe_Largeur-1; - Fin_Y=Debut_Y+Loupe_Hauteur-1; - - Ligne_horizontale_XOR(Debut_X,Debut_Y,Loupe_Largeur); - Ligne_verticale_XOR(Debut_X,Debut_Y+1,Loupe_Hauteur-2); - Ligne_verticale_XOR( Fin_X,Debut_Y+1,Loupe_Hauteur-2); - Ligne_horizontale_XOR(Debut_X, Fin_Y,Loupe_Largeur); - - UpdateRect(Debut_X,Debut_Y,Fin_X+1-Debut_X,Fin_Y+1-Debut_Y); - - break; - default: //case FORME_CURSEUR_ROTATE_XOR : - Debut_X=1-(Brosse_Largeur>>1); - Debut_Y=1-(Brosse_Hauteur>>1); - Fin_X=Debut_X+Brosse_Largeur-1; - Fin_Y=Debut_Y+Brosse_Hauteur-1; - - if (Brosse_Centre_rotation_defini) - { - if ( (Brosse_Centre_rotation_X==Pinceau_X) - && (Brosse_Centre_rotation_Y==Pinceau_Y) ) - { - cosA=1.0; - sinA=0.0; - } - else - { - Pos_X=Pinceau_X-Brosse_Centre_rotation_X; - Pos_Y=Pinceau_Y-Brosse_Centre_rotation_Y; - cosA=(float)Pos_X/sqrt((Pos_X*Pos_X)+(Pos_Y*Pos_Y)); - sinA=sin(acos(cosA)); - if (Pos_Y>0) sinA=-sinA; - } - - Transformer_point(Debut_X,Debut_Y, cosA,sinA, &X1,&Y1); - Transformer_point(Fin_X ,Debut_Y, cosA,sinA, &X2,&Y2); - Transformer_point(Debut_X,Fin_Y , cosA,sinA, &X3,&Y3); - Transformer_point(Fin_X ,Fin_Y , cosA,sinA, &X4,&Y4); - - X1+=Brosse_Centre_rotation_X; - Y1+=Brosse_Centre_rotation_Y; - X2+=Brosse_Centre_rotation_X; - Y2+=Brosse_Centre_rotation_Y; - X3+=Brosse_Centre_rotation_X; - Y3+=Brosse_Centre_rotation_Y; - X4+=Brosse_Centre_rotation_X; - Y4+=Brosse_Centre_rotation_Y; - Pixel_figure_Preview_xor(Brosse_Centre_rotation_X,Brosse_Centre_rotation_Y,0); - Tracer_ligne_Preview_xor(Brosse_Centre_rotation_X,Brosse_Centre_rotation_Y,Pinceau_X,Pinceau_Y,0); - } - else - { - X1=X3=1-Brosse_Largeur; - Y1=Y2=Debut_Y; - X2=X4=Pinceau_X; - Y3=Y4=Fin_Y; - - X1+=Pinceau_X; - Y1+=Pinceau_Y; - Y2+=Pinceau_Y; - X3+=Pinceau_X; - Y3+=Pinceau_Y; - Y4+=Pinceau_Y; - Pixel_figure_Preview_xor(Pinceau_X-Fin_X,Pinceau_Y,0); - Tracer_ligne_Preview_xor(Pinceau_X-Fin_X,Pinceau_Y,Pinceau_X,Pinceau_Y,0); - } - - Tracer_ligne_Preview_xor(X1,Y1,X2,Y2,0); - Tracer_ligne_Preview_xor(X2,Y2,X4,Y4,0); - Tracer_ligne_Preview_xor(X4,Y4,X3,Y3,0); - Tracer_ligne_Preview_xor(X3,Y3,X1,Y1,0); - } -} - - // -- Effacer le curseur -- - -void Effacer_curseur(void) -{ - byte Forme; - int Debut_X; // int car sont parfois négatifs ! (quand on dessine sur un bord) - int Debut_Y; - short Fin_X; - short Fin_Y; - int Pos_X; - int Pos_Y; - short Compteur_X; - short Compteur_Y; - //short Fin_Compteur_X; // Position X ou s'arrête l'affichage de la brosse/pinceau - //short Fin_Compteur_Y; // Position Y ou s'arrête l'affichage de la brosse/pinceau - int Temp; - //byte Couleur; - float cosA,sinA; - short X1,Y1,X2,Y2,X3,Y3,X4,Y4; - - if ( ( (Mouse_Y=Principal_X_Zoom) ) ) - || (Fenetre) || (Forme_curseur==FORME_CURSEUR_SABLIER) ) - Forme=Forme_curseur; - else - Forme=FORME_CURSEUR_FLECHE; - - switch(Forme) - { - case FORME_CURSEUR_CIBLE : - if (!Cacher_curseur) - { - if (Config.Curseur==1) - { - Debut_Y=(Mouse_Y<6)?6-Mouse_Y:0; - if (Debut_Y<4) - Ligne_verticale_XOR (Mouse_X,Mouse_Y+Debut_Y-6,4-Debut_Y); - - Debut_X=(Mouse_X<6)?(short)6-Mouse_X:0; - if (Debut_X<4) - Ligne_horizontale_XOR(Mouse_X+Debut_X-6,Mouse_Y,4-Debut_X); - - Fin_X=(Mouse_X+7>Largeur_ecran)?Mouse_X+7-Largeur_ecran:0; - if (Fin_X<4) - Ligne_horizontale_XOR(Mouse_X+3,Mouse_Y,4-Fin_X); - - Fin_Y=(Mouse_Y+7>Hauteur_ecran)?Mouse_Y+7-Hauteur_ecran:0; - if (Fin_Y<4) - Ligne_verticale_XOR (Mouse_X,Mouse_Y+3,4-Fin_Y); - - UpdateRect(Mouse_X+Debut_X-6,Mouse_Y+Debut_Y-6,12-Fin_X,12-Fin_Y); - } - else - { - Temp=(Config.Curseur)?FORME_CURSEUR_CIBLE_FINE:FORME_CURSEUR_CIBLE; - Debut_X=Mouse_X-Curseur_Decalage_X[Temp]; - Debut_Y=Mouse_Y-Curseur_Decalage_Y[Temp]; - - for (Pos_Y=Debut_Y,Compteur_Y=0;Compteur_Y<15;Pos_Y++,Compteur_Y++) - { - if(Pos_Y>=Hauteur_ecran) break; - for (Pos_X=Debut_X,Compteur_X=0;Compteur_X<15;Pos_X++,Compteur_X++) - { - if ( (Pos_X<0) || (Pos_Y < 0)) continue; - else if (Pos_X>=Largeur_ecran) break; - Pixel(Pos_X,Pos_Y,FOND_CURSEUR[Compteur_Y][Compteur_X]); - } - } - - UpdateRect(Max(Debut_X,0),Max(Debut_Y,0),Pos_X-Debut_X,Pos_Y-Debut_Y); - } - } - if (!Cacher_pinceau) - { - Effacer_pinceau(Pinceau_X,Pinceau_Y); - } - break; - - case FORME_CURSEUR_CIBLE_PIPETTE: - if (!Cacher_curseur) - { - if (Config.Curseur==1) - { - // Barres formant la croix principale - - Debut_Y=(Mouse_Y<5)?5-Mouse_Y:0; - if (Debut_Y<3) - Ligne_verticale_XOR (Mouse_X,Mouse_Y+Debut_Y-5,3-Debut_Y); - - Debut_X=(Mouse_X<5)?(short)5-Mouse_X:0; - if (Debut_X<3) - Ligne_horizontale_XOR(Mouse_X+Debut_X-5,Mouse_Y,3-Debut_X); - - Fin_X=(Mouse_X+6>Largeur_ecran)?Mouse_X+6-Largeur_ecran:0; - if (Fin_X<3) - Ligne_horizontale_XOR(Mouse_X+3,Mouse_Y,3-Fin_X); - - Fin_Y=(Mouse_Y+6>Hauteur_ecran)?Mouse_Y+6-Hauteur_ecran:0; - if (Fin_Y<3) - Ligne_verticale_XOR (Mouse_X,Mouse_Y+3,3-Fin_Y); - - Debut_X=(!Mouse_X); - Debut_Y=(!Mouse_Y); - Fin_X=(Mouse_X>=Largeur_ecran-1); - Fin_Y=(Mouse_Y>=Menu_Ordonnee-1); - - if (Mouse_Y>5) - Ligne_horizontale_XOR(Debut_X+Mouse_X-1,Mouse_Y-6,3-(Debut_X+Fin_X)); - - if (Mouse_X>5) - Ligne_verticale_XOR (Mouse_X-6,Debut_Y+Mouse_Y-1,3-(Debut_Y+Fin_Y)); - - if (Mouse_X=0) && (Pos_X=0) && (Pos_Y=Largeur_ecran) break; - for (Pos_Y=Debut_Y,Compteur_Y=0;Compteur_Y<15;Pos_Y++,Compteur_Y++) - { - if(Pos_Y<0) continue; - if(Pos_Y>=Hauteur_ecran) break; - Pixel(Pos_X,Pos_Y,FOND_CURSEUR[Compteur_Y][Compteur_X]); - } - } - UpdateRect(Max(Debut_X,0),Max(Debut_Y,0),Compteur_X,Compteur_Y); - break; - - case FORME_CURSEUR_CIBLE_XOR : - Pos_X=Pinceau_X-Principal_Decalage_X; - Pos_Y=Pinceau_Y-Principal_Decalage_Y; - - Compteur_X=(Loupe_Mode)?Principal_Split:Largeur_ecran; // Largeur de la barre XOR - if ((Pos_Y=Limite_Haut)) - { - Ligne_horizontale_XOR(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X); - UpdateRect(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X,1); - } - - if ((Pos_X=Limite_Gauche)) - { - Ligne_verticale_XOR(Pinceau_X-Principal_Decalage_X,0,Menu_Ordonnee); - UpdateRect(Pinceau_X-Principal_Decalage_X,0,1,Menu_Ordonnee); - } - - if (Loupe_Mode) - { - // UPDATERECT - if ((Pinceau_Y>=Limite_Haut_Zoom) && (Pinceau_Y<=Limite_visible_Bas_Zoom)) - Ligne_horizontale_XOR_Zoom(Limite_Gauche_Zoom,Pinceau_Y,Loupe_Largeur); - if ((Pinceau_X>=Limite_Gauche_Zoom) && (Pinceau_X<=Limite_visible_Droite_Zoom)) - Ligne_verticale_XOR_Zoom(Pinceau_X,Limite_Haut_Zoom,Loupe_Hauteur); - } - - - break; - case FORME_CURSEUR_RECTANGLE_XOR : - // !!! Cette forme ne peut pas être utilisée en mode Loupe !!! - - // Petite croix au centre - Debut_X=(Mouse_X-3); - Debut_Y=(Mouse_Y-3); - Fin_X =(Mouse_X+4); - Fin_Y =(Mouse_Y+4); - if (Debut_X<0) - Debut_X=0; - if (Debut_Y<0) - Debut_Y=0; - if (Fin_X>Largeur_ecran) - Fin_X=Largeur_ecran; - if (Fin_Y>Menu_Ordonnee) - Fin_Y=Menu_Ordonnee; - - Ligne_horizontale_XOR(Debut_X,Mouse_Y,Fin_X-Debut_X); - Ligne_verticale_XOR (Mouse_X,Debut_Y,Fin_Y-Debut_Y); - - // Grand rectangle autour - - Debut_X=Mouse_X-(Loupe_Largeur>>1); - Debut_Y=Mouse_Y-(Loupe_Hauteur>>1); - if (Debut_X+Loupe_Largeur>=Limite_Droite-Principal_Decalage_X) - Debut_X=Limite_Droite-Loupe_Largeur-Principal_Decalage_X+1; - if (Debut_Y+Loupe_Hauteur>=Limite_Bas-Principal_Decalage_Y) - Debut_Y=Limite_Bas-Loupe_Hauteur-Principal_Decalage_Y+1; - if (Debut_X<0) - Debut_X=0; - if (Debut_Y<0) - Debut_Y=0; - Fin_X=Debut_X+Loupe_Largeur-1; - Fin_Y=Debut_Y+Loupe_Hauteur-1; - - Ligne_horizontale_XOR(Debut_X,Debut_Y,Loupe_Largeur); - Ligne_verticale_XOR(Debut_X,Debut_Y+1,Loupe_Hauteur-2); - Ligne_verticale_XOR( Fin_X,Debut_Y+1,Loupe_Hauteur-2); - Ligne_horizontale_XOR(Debut_X, Fin_Y,Loupe_Largeur); - - UpdateRect(Debut_X,Debut_Y,Fin_X+1-Debut_X,Fin_Y+1-Debut_Y); - - break; - default: //case FORME_CURSEUR_ROTATE_XOR : - Debut_X=1-(Brosse_Largeur>>1); - Debut_Y=1-(Brosse_Hauteur>>1); - Fin_X=Debut_X+Brosse_Largeur-1; - Fin_Y=Debut_Y+Brosse_Hauteur-1; - - if (Brosse_Centre_rotation_defini) - { - if ( (Brosse_Centre_rotation_X==Pinceau_X) - && (Brosse_Centre_rotation_Y==Pinceau_Y) ) - { - cosA=1.0; - sinA=0.0; - } - else - { - Pos_X=Pinceau_X-Brosse_Centre_rotation_X; - Pos_Y=Pinceau_Y-Brosse_Centre_rotation_Y; - cosA=(float)Pos_X/sqrt((Pos_X*Pos_X)+(Pos_Y*Pos_Y)); - sinA=sin(acos(cosA)); - if (Pos_Y>0) sinA=-sinA; - } - - Transformer_point(Debut_X,Debut_Y, cosA,sinA, &X1,&Y1); - Transformer_point(Fin_X ,Debut_Y, cosA,sinA, &X2,&Y2); - Transformer_point(Debut_X,Fin_Y , cosA,sinA, &X3,&Y3); - Transformer_point(Fin_X ,Fin_Y , cosA,sinA, &X4,&Y4); - - X1+=Brosse_Centre_rotation_X; - Y1+=Brosse_Centre_rotation_Y; - X2+=Brosse_Centre_rotation_X; - Y2+=Brosse_Centre_rotation_Y; - X3+=Brosse_Centre_rotation_X; - Y3+=Brosse_Centre_rotation_Y; - X4+=Brosse_Centre_rotation_X; - Y4+=Brosse_Centre_rotation_Y; - Pixel_figure_Preview_xor(Brosse_Centre_rotation_X,Brosse_Centre_rotation_Y,0); - Tracer_ligne_Preview_xor(Brosse_Centre_rotation_X,Brosse_Centre_rotation_Y,Pinceau_X,Pinceau_Y,0); - } - else - { - X1=X3=1-Brosse_Largeur; - Y1=Y2=Debut_Y; - X2=X4=Pinceau_X; - Y3=Y4=Fin_Y; - - X1+=Pinceau_X; - Y1+=Pinceau_Y; - Y2+=Pinceau_Y; - X3+=Pinceau_X; - Y3+=Pinceau_Y; - Y4+=Pinceau_Y; - Pixel_figure_Preview_xor(Pinceau_X-Fin_X,Pinceau_Y,0); - Tracer_ligne_Preview_xor(Pinceau_X-Fin_X,Pinceau_Y,Pinceau_X,Pinceau_Y,0); - } - - Tracer_ligne_Preview_xor(X1,Y1,X2,Y2,0); - Tracer_ligne_Preview_xor(X2,Y2,X4,Y4,0); - Tracer_ligne_Preview_xor(X4,Y4,X3,Y3,0); - Tracer_ligne_Preview_xor(X3,Y3,X1,Y1,0); - } -} - - - -//---- Fenêtre demandant de confirmer une action et renvoyant la réponse ----- -byte Demande_de_confirmation(char * Message) -{ - short Bouton_clicke; - word Largeur_de_la_fenetre; - - Largeur_de_la_fenetre=(strlen(Message)<<3)+20; - - if (Largeur_de_la_fenetre<120) - Largeur_de_la_fenetre=120; - - Ouvrir_fenetre(Largeur_de_la_fenetre,60,"Confirmation"); - - Print_dans_fenetre((Largeur_de_la_fenetre>>1)-(strlen(Message)<<2),20,Message,CM_Noir,CM_Clair); - - Fenetre_Definir_bouton_normal((Largeur_de_la_fenetre/3)-20 ,37,40,14,"Yes",1,1,SDLK_y); // 1 - Fenetre_Definir_bouton_normal(((Largeur_de_la_fenetre<<1)/3)-20,37,40,14,"No" ,1,1,SDLK_n); // 2 - - UpdateRect(Fenetre_Pos_X,Fenetre_Pos_Y,Menu_Facteur_X*Largeur_de_la_fenetre,Menu_Facteur_Y*60); - - Afficher_curseur(); - - do - { - Bouton_clicke=Fenetre_Bouton_clicke(); - if (Touche==SDLK_RETURN) Bouton_clicke=1; - if (Touche==SDLK_ESCAPE) Bouton_clicke=2; - } - while (Bouton_clicke<=0); - - Fermer_fenetre(); - Afficher_curseur(); - - return (Bouton_clicke==1)? 1 : 0; -} - - - -//---- Fenêtre avertissant de quelque chose et attendant un click sur OK ----- -void Warning_message(char * Message) -{ - short Bouton_clicke; - word Largeur_de_la_fenetre; - - Largeur_de_la_fenetre=(strlen(Message)<<3)+20; - if (Largeur_de_la_fenetre<120) - Largeur_de_la_fenetre=120; - - Ouvrir_fenetre(Largeur_de_la_fenetre,60,"Warning!"); - - Print_dans_fenetre((Largeur_de_la_fenetre>>1)-(strlen(Message)<<2),20,Message,CM_Noir,CM_Clair); - Fenetre_Definir_bouton_normal((Largeur_de_la_fenetre>>1)-20 ,37,40,14,"OK",1,1,SDLK_RETURN); // 1 - UpdateRect(Fenetre_Pos_X,Fenetre_Pos_Y,Menu_Facteur_X*Largeur_de_la_fenetre,Menu_Facteur_Y*60); - Afficher_curseur(); - - do - Bouton_clicke=Fenetre_Bouton_clicke(); - while ((Bouton_clicke<=0) && (Touche!=SDLK_ESCAPE) && (Touche!=SDLK_o)); - - Fermer_fenetre(); - Afficher_curseur(); -} - - - -// -- Fonction diverses d'affichage ------------------------------------------ - - // -- Reafficher toute l'image (en prenant en compte le facteur de zoom) -- - -void Afficher_ecran(void) -{ - word Largeur; - word Hauteur; - - // ---/\/\/\ Partie non zoomée: /\/\/\--- - if (Loupe_Mode) - { - if (Principal_Largeur_image à 64 lignes fct(Menu_Facteur) - word Nb_couleurs =(Debut_block<=Fin_block)?Fin_block-Debut_block+1:Debut_block-Fin_block+1; - word Ligne_en_cours=(Debut_block<=Fin_block)?0:Total_lignes-1; - - word Debut_X =Fenetre_Pos_X+(Menu_Facteur_X*Pos_X); - word Largeur_ligne =Menu_Facteur_X<<4; // <=> à 16 pixels fct(Menu_Facteur) - - word Debut_Y =Fenetre_Pos_Y+(Menu_Facteur_Y*Pos_Y); - word Fin_Y =Debut_Y+Total_lignes; - word Indice; - - if (Debut_block>Fin_block) - { - Indice=Debut_block; - Debut_block=Fin_block; - Fin_block=Indice; - } - - for (Indice=Debut_Y;IndiceFin_X) - { - Temporaire=Debut_X; - Debut_X =Fin_X; - Fin_X =Temporaire; - } - if (Debut_Y>Fin_Y) - { - Temporaire=Debut_Y; - Debut_Y =Fin_Y; - Fin_Y =Temporaire; - } - - // On ne capture la nouvelle brosse que si elle est au moins partiellement - // dans l'image: - - if ((Debut_XPrincipal_Largeur_image) - Nouvelle_Brosse_Largeur=Principal_Largeur_image-Debut_X; - if (Debut_Y+Nouvelle_Brosse_Hauteur>Principal_Hauteur_image) - Nouvelle_Brosse_Hauteur=Principal_Hauteur_image-Debut_Y; - - if ( (((long)Brosse_Hauteur)*Brosse_Largeur) != - (((long)Nouvelle_Brosse_Hauteur)*Nouvelle_Brosse_Largeur) ) - { - free(Brosse); - Brosse=(byte *)malloc(((long)Nouvelle_Brosse_Hauteur)*Nouvelle_Brosse_Largeur); - if (!Brosse) - { - Erreur(0); - - Brosse=(byte *)malloc(1*1); - Nouvelle_Brosse_Hauteur=Nouvelle_Brosse_Largeur=1; - *Brosse=Fore_color; - } - } - Brosse_Largeur=Nouvelle_Brosse_Largeur; - Brosse_Hauteur=Nouvelle_Brosse_Hauteur; - - free(Smear_Brosse); - Smear_Brosse_Largeur=(Brosse_Largeur>TAILLE_MAXI_PINCEAU)?Brosse_Largeur:TAILLE_MAXI_PINCEAU; - Smear_Brosse_Hauteur=(Brosse_Hauteur>TAILLE_MAXI_PINCEAU)?Brosse_Hauteur:TAILLE_MAXI_PINCEAU; - Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Hauteur)*Smear_Brosse_Largeur); - - if (!Smear_Brosse) // On ne peut même pas allouer la brosse du smear! - { - Erreur(0); - - free(Brosse); - Brosse=(byte *)malloc(1*1); - Brosse_Hauteur=1; - Brosse_Largeur=1; - - Smear_Brosse=(byte *)malloc(TAILLE_MAXI_PINCEAU*TAILLE_MAXI_PINCEAU); - Smear_Brosse_Hauteur=TAILLE_MAXI_PINCEAU; - Smear_Brosse_Largeur=TAILLE_MAXI_PINCEAU; - } - - Copier_image_dans_brosse(Debut_X,Debut_Y,Brosse_Largeur,Brosse_Hauteur,Principal_Largeur_image); - - // On regarde s'il faut effacer quelque chose: - if (Effacement) - { - for (Pos_Y=Debut_Y;Pos_Y>1); - Brosse_Decalage_Y=(Brosse_Hauteur>>1); - } -} - - -void Rotate_90_deg() -{ - short Temporaire; - byte * Nouvelle_Brosse; - - Nouvelle_Brosse=(byte *)malloc(((long)Brosse_Hauteur)*Brosse_Largeur); - if (Nouvelle_Brosse) - { - Rotate_90_deg_LOWLEVEL(Brosse,Nouvelle_Brosse); - free(Brosse); - Brosse=Nouvelle_Brosse; - - Temporaire=Brosse_Largeur; - Brosse_Largeur=Brosse_Hauteur; - Brosse_Hauteur=Temporaire; - - Temporaire=Smear_Brosse_Largeur; - Smear_Brosse_Largeur=Smear_Brosse_Hauteur; - Smear_Brosse_Hauteur=Temporaire; - - // On centre la prise sur la brosse - Brosse_Decalage_X=(Brosse_Largeur>>1); - Brosse_Decalage_Y=(Brosse_Hauteur>>1); - } - else - Erreur(0); -} - - -void Remap_brosse(void) -{ - short Pos_X; // Variable de balayage de la brosse - short Pos_Y; // Variable de balayage de la brosse - byte Utilisee[256]; // Tableau de booléens "La couleur est utilisée" - int Couleur; - - - // On commence par initialiser le tableau de booléens à faux - for (Couleur=0;Couleur<=255;Couleur++) - Utilisee[Couleur]=0; - - // On calcule la table d'utilisation des couleurs - for (Pos_Y=0;Pos_Y>1); - Brosse_Decalage_Y=(Brosse_Hauteur>>1); - - free(Temporaire); // Libération de l'ancienne brosse - - // Réallocation d'un buffer de Smear - free(Smear_Brosse); - Smear_Brosse_Largeur=(Brosse_Largeur>TAILLE_MAXI_PINCEAU)?Brosse_Largeur:TAILLE_MAXI_PINCEAU; - Smear_Brosse_Hauteur=(Brosse_Hauteur>TAILLE_MAXI_PINCEAU)?Brosse_Hauteur:TAILLE_MAXI_PINCEAU; - Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Largeur)*Smear_Brosse_Hauteur); - } - else - Erreur(0); // Pas assez de mémoire! -} - - -void Nibble_brush(void) -{ - long /*Pos,*/Pos_X,Pos_Y; - byte Etat; - byte * Nouvelle_brosse; - byte * Temporaire; - word Largeur; - word Hauteur; - - if ( (Brosse_Largeur>2) && (Brosse_Hauteur>2) ) - { - Largeur=Brosse_Largeur-2; - Hauteur=Brosse_Hauteur-2; - Nouvelle_brosse=(byte *)malloc(((long)Largeur)*Hauteur); - - if (Nouvelle_brosse) - { - // On copie la brosse courante dans la nouvelle - Copier_une_partie_d_image_dans_une_autre(Brosse, // Source - 1, - 1, - Largeur, - Hauteur, - Brosse_Largeur, - Nouvelle_brosse, // Destination - 0, - 0, - Largeur); - - // On intervertit la nouvelle et l'ancienne brosse: - Temporaire=Brosse; - Brosse=Nouvelle_brosse; - Brosse_Largeur-=2; - Brosse_Hauteur-=2; - Largeur+=2; - Hauteur+=2; - - // 1er balayage (horizontal) - for (Pos_Y=0; Pos_Y0) - Pixel_dans_brosse(Pos_X-1,Pos_Y,Back_color); - Etat=0; - } - } - else - { - if (!Etat) - { - Pixel_dans_brosse(Pos_X,Pos_Y,Back_color); - Etat=1; - } - } - } - // Cas du dernier pixel à droite de la ligne - if (Temporaire[((Pos_Y+1)*Largeur)+Pos_X+1]==Back_color) - Pixel_dans_brosse(Pos_X-1,Pos_Y,Back_color); - } - - // 2ème balayage (vertical) - for (Pos_X=0; Pos_X0) - Pixel_dans_brosse(Pos_X,Pos_Y-1,Back_color); - Etat=0; - } - } - else - { - if (!Etat) - { - Pixel_dans_brosse(Pos_X,Pos_Y,Back_color); - Etat=1; - } - } - } - // Cas du dernier pixel en bas de la colonne - if (Temporaire[((Pos_Y+1)*Largeur)+Pos_X+1]==Back_color) - Pixel_dans_brosse(Pos_X,Pos_Y-1,Back_color); - } - - // On recentre la prise sur la brosse - Brosse_Decalage_X=(Brosse_Largeur>>1); - Brosse_Decalage_Y=(Brosse_Hauteur>>1); - - free(Temporaire); // Libération de l'ancienne brosse - - // Réallocation d'un buffer de Smear - free(Smear_Brosse); - Smear_Brosse_Largeur=(Brosse_Largeur>TAILLE_MAXI_PINCEAU)?Brosse_Largeur:TAILLE_MAXI_PINCEAU; - Smear_Brosse_Hauteur=(Brosse_Hauteur>TAILLE_MAXI_PINCEAU)?Brosse_Hauteur:TAILLE_MAXI_PINCEAU; - Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Largeur)*Smear_Brosse_Hauteur); - } - else - Erreur(0); // Pas assez de mémoire! - } -} - - ////////////////////////////////////////////////////////////////////////////// ////////////////////////////// GESTION DU FILLER ///////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -4199,7 +515,7 @@ void Fill(short * Limite_atteinte_Haut , short * Limite_atteinte_Bas, while (Debut_X<=Limite_Droite) { // On cherche son début - while((Debut_X<=Limite_Droite) && + while((Debut_X<=Limite_Droite) && (Lit_pixel_dans_ecran_courant(Debut_X,Ligne)!=1)) Debut_X++; @@ -4469,8 +785,6 @@ void Remplir(byte Couleur_de_remplissage) ////////////////////////// avec gestion de previews ////////////////////////// ////////////////////////////////////////////////////////////////////////////// - // Définition d'une fonction générique de traçage de figures: - fonction_afficheur Pixel_figure; // Affichage d'un point de façon définitive (utilisation du pinceau) inline void Pixel_figure_Definitif(word Pos_X,word Pos_Y,byte Couleur) @@ -5070,7 +1384,7 @@ void Tracer_courbe_General(short X1, short Y1, Old_X=X; Old_Y=Y; } - + X = Min(Min(X1,X2),Min(X3,X4)); Y = Min(Min(Y1,Y2),Min(Y3,Y4)); Old_X = Max(Max(X1,X2),Max(X3,X4)) - X; @@ -5378,10 +1692,6 @@ void Degrade_de_trames_etendues(long Indice,short Pos_X,short Pos_Y) - - - - // -- Tracer un cercle degradé (une sphère) -- void Tracer_cercle_degrade(short Centre_X,short Centre_Y,short Rayon,short Eclairage_X,short Eclairage_Y) @@ -5433,7 +1743,7 @@ void Tracer_cercle_degrade(short Centre_X,short Centre_Y,short Rayon,short Eclai Traiter_degrade(Distance_X+Distance_Y,Pos_X,Pos_Y); } } - + Mettre_Ecran_A_Jour(Centre_X-Rayon,Centre_Y-Rayon,2*Rayon+1,2*Rayon+1); } @@ -5801,134 +2111,6 @@ void Polyfill(int Vertices, short * Points, int Color) -void Capturer_brosse_au_lasso(int Vertices, short * Points,short Effacement) -{ - short Debut_X=Limite_Droite+1; - short Debut_Y=Limite_Bas+1; - short Fin_X=Limite_Gauche-1; - short Fin_Y=Limite_Haut-1; - short Temporaire; - short Pos_X; - short Pos_Y; - word Nouvelle_Brosse_Largeur; - word Nouvelle_Brosse_Hauteur; - - - // On recherche les bornes de la brosse: - for (Temporaire=0; TemporaireFin_X) - Fin_X=Pos_X; - if (Pos_YFin_Y) - Fin_Y=Pos_Y; - } - - // On clippe ces bornes à l'écran: - if (Debut_XLimite_Droite) - Fin_X=Limite_Droite; - if (Debut_YLimite_Bas) - Fin_Y=Limite_Bas; - - // On ne capture la nouvelle brosse que si elle est au moins partiellement - // dans l'image: - - if ((Debut_XTAILLE_MAXI_PINCEAU)?Brosse_Largeur:TAILLE_MAXI_PINCEAU; - Smear_Brosse_Hauteur=(Brosse_Hauteur>TAILLE_MAXI_PINCEAU)?Brosse_Hauteur:TAILLE_MAXI_PINCEAU; - Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Hauteur)*Smear_Brosse_Largeur); - - if (!Smear_Brosse) // On ne peut même pas allouer la brosse du smear! - { - Erreur(0); - - free(Brosse); - Brosse=(byte *)malloc(1*1); - Brosse_Hauteur=1; - Brosse_Largeur=1; - - Smear_Brosse=(byte *)malloc(TAILLE_MAXI_PINCEAU*TAILLE_MAXI_PINCEAU); - Smear_Brosse_Hauteur=TAILLE_MAXI_PINCEAU; - Smear_Brosse_Largeur=TAILLE_MAXI_PINCEAU; - } - - Brosse_Decalage_X=Debut_X; - Brosse_Decalage_Y=Debut_Y; - Pixel_figure=Pixel_figure_Dans_brosse; - - memset(Brosse,Back_color,(long)Brosse_Largeur*Brosse_Hauteur); - Polyfill_General(Vertices,Points,~Back_color); - - // On retrace les bordures du lasso: - for (Temporaire=1; Temporaire>1); - Brosse_Decalage_Y=(Brosse_Hauteur>>1); - } -} - - - //------------ Remplacement de la couleur pointée par une autre -------------- void Remplacer(byte Nouvelle_couleur) @@ -5949,625 +2131,263 @@ void Remplacer(byte Nouvelle_couleur) } -//------------------------- Etirement de la brosse --------------------------- -void Etirer_brosse(short X1, short Y1, short X2, short Y2) +/******************************************************************************/ +/********************************** SHADES ************************************/ + +// Transformer une liste de shade en deux tables de conversion +void Liste2tables(word * Liste,short Pas,byte Mode,byte * Table_inc,byte * Table_dec) { - int Offset,Ligne,Colonne; - byte * New_Brosse; + int Indice; + int Premier; + int Dernier; + int Couleur; + int Temp; - int New_Brosse_Largeur; // Largeur de la nouvelle brosse - int New_Brosse_Hauteur; // Hauteur de la nouvelle brosse - int Pos_X_dans_brosse; // Position courante dans l'ancienne brosse - int Pos_Y_dans_brosse; - int Delta_X_dans_brosse; // "Vecteur incrémental" du point précédent - int Delta_Y_dans_brosse; - int Pos_X_initial; // Position X de début de parcours de ligne - int Dx,Dy; - - Dx=(X1=0) - Pos_X_initial = 0; // Pas d'inversion en X de la brosse - else - Pos_X_initial = (Brosse_Largeur<<16)-1; // Inversion en X de la brosse - - free(Smear_Brosse); // On libère un peu de mémoire - - if ((New_Brosse=((byte *)malloc(New_Brosse_Largeur*New_Brosse_Hauteur)))) + // On initialise les deux tables de conversion en Identité + for (Indice=0;Indice<256;Indice++) { - Offset=0; + Table_inc[Indice]=Indice; + Table_dec[Indice]=Indice; + } - // Calcul de la valeur initiale de Pos_Y: - if (Dy>=0) - Pos_Y_dans_brosse=0; // Pas d'inversion en Y de la brosse + // On s'apprête à examiner l'ensemble de la liste + for (Indice=0;Indice<512;Indice++) + { + // On recherche la première case de la liste non vide (et non inhibée) + while ((Indice<512) && (Liste[Indice]>255)) + Indice++; + + // On note la position de la première case de la séquence + Premier=Indice; + + // On recherche la position de la dernière case de la séquence + for (Dernier=Premier;Liste[Dernier+1]<256;Dernier++); + + // Pour toutes les cases non vides (et non inhibées) qui suivent + switch (Mode) + { + case MODE_SHADE_NORMAL : + for (;(Indice<512) && (Liste[Indice]<256);Indice++) + { // On met à jour les tables de conversion + Couleur=Liste[Indice]; + Table_inc[Couleur]=Liste[(Indice+Pas<=Dernier)?Indice+Pas:Dernier]; + Table_dec[Couleur]=Liste[(Indice-Pas>=Premier)?Indice-Pas:Premier]; + } + break; + case MODE_SHADE_BOUCLE : + Temp=1+Dernier-Premier; + for (;(Indice<512) && (Liste[Indice]<256);Indice++) + { // On met à jour les tables de conversion + Couleur=Liste[Indice]; + Table_inc[Couleur]=Liste[Premier+((Pas+Indice-Premier)%Temp)]; + Table_dec[Couleur]=Liste[Premier+(((Temp-Pas)+Indice-Premier)%Temp)]; + } + break; + default : // MODE_SHADE_NOSAT + for (;(Indice<512) && (Liste[Indice]<256);Indice++) + { // On met à jour les tables de conversion + Couleur=Liste[Indice]; + if (Indice+Pas<=Dernier) + Table_inc[Couleur]=Liste[Indice+Pas]; + if (Indice-Pas>=Premier) + Table_dec[Couleur]=Liste[Indice-Pas]; + } + } + } +} + + + +// -- Interface avec l'image, affectée par le facteur de grossissement ------- + + // fonction d'affichage "Pixel" utilisée pour les opérations définitivement + // Ne doit à aucune condition être appelée en dehors de la partie visible + // de l'image dans l'écran (ça pourrait être grave) +void Afficher_pixel(word X,word Y,byte Couleur) + // X & Y sont la position d'un point dans l'IMAGE + // Couleur est la couleur du point + // Le Stencil est géré. + // Les effets sont gérés par appel à Fonction_effet(). + // La Loupe est gérée par appel à Pixel_Preview(). +{ + if ( ( (!Trame_Mode) || (Effet_Trame(X,Y)) ) + && (!((Stencil_Mode) && (Stencil[Lit_pixel_dans_ecran_courant(X,Y)]))) + && (!((Mask_Mode) && (Mask_table[Lit_pixel_dans_ecran_brouillon(X,Y)]))) ) + { + Couleur=Fonction_effet(X,Y,Couleur); + Pixel_dans_ecran_courant(X,Y,Couleur); + Pixel_Preview(X,Y,Couleur); + } +} + + + +// -- Calcul des différents effets ------------------------------------------- + + // -- Aucun effet en cours -- + +byte Aucun_effet(__attribute__((unused)) word X,__attribute__((unused)) word Y,byte Couleur) +{ + return Couleur; +} + + // -- Effet de Shading -- + +byte Effet_Shade(word X,word Y,__attribute__((unused)) byte Couleur) +{ + return Shade_Table[Lit_pixel_dans_ecran_feedback(X,Y)]; +} + +byte Effet_Quick_shade(word X,word Y,byte Couleur) +{ + int C=Couleur=Lit_pixel_dans_ecran_feedback(X,Y); + int Sens=(Fore_color<=Back_color); + byte Debut,Fin; + int Largeur; + + if (Sens) + { + Debut=Fore_color; + Fin =Back_color; + } + else + { + Debut=Back_color; + Fin =Fore_color; + } + + if ((C>=Debut) && (C<=Fin) && (Debut!=Fin)) + { + Largeur=1+Fin-Debut; + + if ( ((Mouse_K==A_GAUCHE) && Sens) || ((Mouse_K==A_DROITE) && (!Sens)) ) + C-=Quick_shade_Step%Largeur; else - Pos_Y_dans_brosse=(Brosse_Hauteur<<16)-1; // Inversion en Y de la brosse + C+=Quick_shade_Step%Largeur; - // Pour chaque ligne - for (Ligne=0;Ligne>16,Pos_Y_dans_brosse>>16); - // On passe à la colonne de brosse suivante: - Pos_X_dans_brosse+=Delta_X_dans_brosse; - // On passe au pixel suivant de la nouvelle brosse: - Offset++; + case MODE_SHADE_NORMAL : return Debut; + case MODE_SHADE_BOUCLE : return (Largeur+C); + default : return Couleur; } - // On passe à la ligne de brosse suivante: - Pos_Y_dans_brosse+=Delta_Y_dans_brosse; - } - - free(Brosse); - Brosse=New_Brosse; - - Brosse_Largeur=New_Brosse_Largeur; - Brosse_Hauteur=New_Brosse_Hauteur; - - Smear_Brosse_Largeur=(Brosse_Largeur>TAILLE_MAXI_PINCEAU)?Brosse_Largeur:TAILLE_MAXI_PINCEAU; - Smear_Brosse_Hauteur=(Brosse_Hauteur>TAILLE_MAXI_PINCEAU)?Brosse_Hauteur:TAILLE_MAXI_PINCEAU; - Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Hauteur)*Smear_Brosse_Largeur); - - if (!Smear_Brosse) // On ne peut même pas allouer la brosse du smear! - { - Erreur(0); - - free(Brosse); - Brosse=(byte *)malloc(1*1); - Brosse_Hauteur=1; - Brosse_Largeur=1; - - Smear_Brosse=(byte *)malloc(TAILLE_MAXI_PINCEAU*TAILLE_MAXI_PINCEAU); - Smear_Brosse_Hauteur=TAILLE_MAXI_PINCEAU; - Smear_Brosse_Largeur=TAILLE_MAXI_PINCEAU; - } - - Brosse_Decalage_X=(Brosse_Largeur>>1); - Brosse_Decalage_Y=(Brosse_Hauteur>>1); - } - else - { - // Ici la libération de mémoire n'a pas suffit donc on remet dans l'état - // où c'etait avant. On a juste à réallouer la Smear_Brosse car il y a - // normalement la place pour elle puisque rien d'autre n'a pu être alloué - // entre temps. - Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Hauteur)*Smear_Brosse_Largeur); - Erreur(0); - } -} - - - -void Etirer_brosse_preview(short X1, short Y1, short X2, short Y2) -{ - int Pos_X_src,Pos_Y_src; - int Pos_X_src_Initiale,Pos_Y_src_Initiale; - int Delta_X,Delta_Y; - int Pos_X_dest,Pos_Y_dest; - int Pos_X_dest_Initiale,Pos_Y_dest_Initiale; - int Pos_X_dest_Finale,Pos_Y_dest_Finale; - int Largeur_dest,Hauteur_dest; - byte Couleur; - - - // 1er calcul des positions destination extremes: - Pos_X_dest_Initiale=Min(X1,X2); - Pos_Y_dest_Initiale=Min(Y1,Y2); - Pos_X_dest_Finale =Max(X1,X2); - Pos_Y_dest_Finale =Max(Y1,Y2); - - // Calcul des dimensions de la destination: - Largeur_dest=Pos_X_dest_Finale-Pos_X_dest_Initiale+1; - Hauteur_dest=Pos_Y_dest_Finale-Pos_Y_dest_Initiale+1; - - // Calcul des vecteurs d'incrémentation : - Delta_X=(Brosse_Largeur<<16)/Largeur_dest; - Delta_Y=(Brosse_Hauteur<<16)/Hauteur_dest; - - // 1er calcul de la position X initiale dans la source: - Pos_X_src_Initiale=(Brosse_Largeur<<16)* - (Max(Pos_X_dest_Initiale,Limite_Gauche)- - Pos_X_dest_Initiale)/Largeur_dest; - // Calcul du clip de la destination: - Pos_X_dest_Initiale=Max(Pos_X_dest_Initiale,Limite_Gauche); - Pos_X_dest_Finale =Min(Pos_X_dest_Finale ,Limite_visible_Droite); - // On discute selon l'inversion en X - if (X1>X2) - { - // Inversion -> Inversion du signe de Delta_X - Delta_X=-Delta_X; - Pos_X_src_Initiale=(Brosse_Largeur<<16)-1-Pos_X_src_Initiale; - } - - // 1er calcul de la position Y initiale dans la source: - Pos_Y_src_Initiale=(Brosse_Hauteur<<16)* - (Max(Pos_Y_dest_Initiale,Limite_Haut)- - Pos_Y_dest_Initiale)/Hauteur_dest; - // Calcul du clip de la destination: - Pos_Y_dest_Initiale=Max(Pos_Y_dest_Initiale,Limite_Haut); - Pos_Y_dest_Finale =Min(Pos_Y_dest_Finale ,Limite_visible_Bas); - // On discute selon l'inversion en Y - if (Y1>Y2) - { - // Inversion -> Inversion du signe de Delta_Y - Delta_Y=-Delta_Y; - Pos_Y_src_Initiale=(Brosse_Hauteur<<16)-1-Pos_Y_src_Initiale; - } - - // Pour chaque ligne : - Pos_Y_src=Pos_Y_src_Initiale; - for (Pos_Y_dest=Pos_Y_dest_Initiale;Pos_Y_dest<=Pos_Y_dest_Finale;Pos_Y_dest++) - { - // Pour chaque colonne: - Pos_X_src=Pos_X_src_Initiale; - for (Pos_X_dest=Pos_X_dest_Initiale;Pos_X_dest<=Pos_X_dest_Finale;Pos_X_dest++) - { - Couleur=Lit_pixel_dans_brosse(Pos_X_src>>16,Pos_Y_src>>16); - if (Couleur!=Back_color) - Pixel_Preview(Pos_X_dest,Pos_Y_dest,Couleur); - - Pos_X_src+=Delta_X; - } - - Pos_Y_src+=Delta_Y; - } - UpdateRect(Pos_X_dest_Initiale,Pos_Y_dest_Initiale,Largeur_dest,Hauteur_dest); -} - - - -//------------------------- Rotation de la brosse --------------------------- - -#define INDEFINI (-1.0e20F) -float * ScanY_Xt[2]; -float * ScanY_Yt[2]; -float * ScanY_X[2]; - - -void Interpoler_texture(int Debut_X,int Debut_Y,int Xt1,int Yt1, - int Fin_X ,int Fin_Y ,int Xt2,int Yt2,int Hauteur) -{ - int Pos_X,Pos_Y; - int Incr_X,Incr_Y; - int i,Cumul; - int Delta_X,Delta_Y; - int Delta_Xt=Xt2-Xt1; - int Delta_Yt=Yt2-Yt1; - int Delta_X2=Fin_X-Debut_X; - int Delta_Y2=Fin_Y-Debut_Y; - float Xt,Yt; - - - Pos_X=Debut_X; - Pos_Y=Debut_Y; - - if (Debut_XDelta_Y) - { - Cumul=Delta_X>>1; - for (i=0; i<=Delta_X; i++) - { - if (Cumul>=Delta_X) + if (C>Fin) + switch (Quick_shade_Loop) { - Cumul-=Delta_X; - Pos_Y+=Incr_Y; + case MODE_SHADE_NORMAL : return Fin; + case MODE_SHADE_BOUCLE : return (C-Largeur); + default : return Couleur; } + } - if ((Pos_Y>=0) && (Pos_Y=ScanY_X[0][Pos_Y]) - { - if ((ScanY_X[1][Pos_Y]==INDEFINI) // Droit non défini - || (Pos_X>ScanY_X[1][Pos_Y])) - { - ScanY_X[1][Pos_Y]=Pos_X; - ScanY_Xt[1][Pos_Y]=Xt; - ScanY_Yt[1][Pos_Y]=Yt; - } - } - else - { - if (ScanY_X[1][Pos_Y]==INDEFINI) // Droit non défini - { - ScanY_X[1][Pos_Y]=ScanY_X[0][Pos_Y]; - ScanY_Xt[1][Pos_Y]=ScanY_Xt[0][Pos_Y]; - ScanY_Yt[1][Pos_Y]=ScanY_Yt[0][Pos_Y]; - ScanY_X[0][Pos_Y]=Pos_X; - ScanY_Xt[0][Pos_Y]=Xt; - ScanY_Yt[0][Pos_Y]=Yt; - } - else - { - ScanY_X[0][Pos_Y]=Pos_X; - ScanY_Xt[0][Pos_Y]=Xt; - ScanY_Yt[0][Pos_Y]=Yt; - } - } - } + C=Lit_pixel_dans_ecran_feedback(X-1,Y+1); + Poids_total+=(Poids=Smooth_Matrice[0][2]); + R+=Poids*Principal_Palette[C].R; + V+=Poids*Principal_Palette[C].V; + B+=Poids*Principal_Palette[C].B; } - Pos_X+=Incr_X; - Cumul+=Delta_Y; } } - else + + if (X2) { - Cumul=Delta_Y>>1; - for (i=0; i<=Delta_Y; i++) + C=Lit_pixel_dans_ecran_feedback(X+1,Y); + Poids_total+=(Poids=Smooth_Matrice[2][1]); + R+=Poids*Principal_Palette[C].R; + V+=Poids*Principal_Palette[C].V; + B+=Poids*Principal_Palette[C].B; + + if (Y) { - if (Cumul>=Delta_Y) + C=Lit_pixel_dans_ecran_feedback(X+1,Y-1); + Poids_total+=(Poids=Smooth_Matrice[2][0]); + R+=Poids*Principal_Palette[C].R; + V+=Poids*Principal_Palette[C].V; + B+=Poids*Principal_Palette[C].B; + + if (Y2) { - Cumul-=Delta_Y; - Pos_X+=Incr_X; + C=Lit_pixel_dans_ecran_feedback(X+1,Y+1); + Poids_total+=(Poids=Smooth_Matrice[2][2]); + R+=Poids*Principal_Palette[C].R; + V+=Poids*Principal_Palette[C].V; + B+=Poids*Principal_Palette[C].B; } - - if ((Pos_Y>=0) && (Pos_Y=ScanY_X[0][Pos_Y]) - { - if ((ScanY_X[1][Pos_Y]==INDEFINI) // Droit non défini - || (Pos_X>ScanY_X[1][Pos_Y])) - { - ScanY_X[1][Pos_Y]=Pos_X; - ScanY_Xt[1][Pos_Y]=Xt; - ScanY_Yt[1][Pos_Y]=Yt; - } - } - else - { - if (ScanY_X[1][Pos_Y]==INDEFINI) // Droit non défini - { - ScanY_X[1][Pos_Y]=ScanY_X[0][Pos_Y]; - ScanY_Xt[1][Pos_Y]=ScanY_Xt[0][Pos_Y]; - ScanY_Yt[1][Pos_Y]=ScanY_Yt[0][Pos_Y]; - ScanY_X[0][Pos_Y]=Pos_X; - ScanY_Xt[0][Pos_Y]=Xt; - ScanY_Yt[0][Pos_Y]=Yt; - } - else - { - ScanY_X[0][Pos_Y]=Pos_X; - ScanY_Xt[0][Pos_Y]=Xt; - ScanY_Yt[0][Pos_Y]=Yt; - } - } - } - } - Pos_Y+=Incr_Y; - Cumul+=Delta_X; - } - } -} - - - -void Calculer_quad_texture(int X1,int Y1,int Xt1,int Yt1, - int X2,int Y2,int Xt2,int Yt2, - int X3,int Y3,int Xt3,int Yt3, - int X4,int Y4,int Xt4,int Yt4, - byte * Buffer, int Largeur, int Hauteur) -{ - int Xmin,/*Xmax,*/Ymin/*,Ymax*/; - int X,Y,Xt,Yt; - int Debut_X,Fin_X,Largeur_ligne; - float Temp; - //byte Couleur; - - Xmin=Min(Min(X1,X2),Min(X3,X4)); - Ymin=Min(Min(Y1,Y2),Min(Y3,Y4)); - - ScanY_Xt[0]=(float *)malloc(Hauteur*sizeof(float)); - ScanY_Xt[1]=(float *)malloc(Hauteur*sizeof(float)); - ScanY_Yt[0]=(float *)malloc(Hauteur*sizeof(float)); - ScanY_Yt[1]=(float *)malloc(Hauteur*sizeof(float)); - ScanY_X[0] =(float *)malloc(Hauteur*sizeof(float)); - ScanY_X[1] =(float *)malloc(Hauteur*sizeof(float)); - - // Remplir avec des valeurs égales à INDEFINI. - for (Y=0; Y>1); - Debut_Y=1-(Brosse_Hauteur>>1); - Fin_X=Debut_X+Brosse_Largeur-1; - Fin_Y=Debut_Y+Brosse_Hauteur-1; - - Transformer_point(Debut_X,Debut_Y, cosA,sinA, &X1,&Y1); - Transformer_point(Fin_X ,Debut_Y, cosA,sinA, &X2,&Y2); - Transformer_point(Debut_X,Fin_Y , cosA,sinA, &X3,&Y3); - Transformer_point(Fin_X ,Fin_Y , cosA,sinA, &X4,&Y4); - - // Calcul des nouvelles dimensions de la brosse: - Xmin=Min(Min((int)X1,(int)X2),Min((int)X3,(int)X4)); - Xmax=Max(Max((int)X1,(int)X2),Max((int)X3,(int)X4)); - Ymin=Min(Min((int)Y1,(int)Y2),Min((int)Y3,(int)Y4)); - Ymax=Max(Max((int)Y1,(int)Y2),Max((int)Y3,(int)Y4)); - - New_Brosse_Largeur=Xmax+1-Xmin; - New_Brosse_Hauteur=Ymax+1-Ymin; - - free(Smear_Brosse); // On libère un peu de mémoire - - if ((New_Brosse=((byte *)malloc(New_Brosse_Largeur*New_Brosse_Hauteur)))) - { - // Et maintenant on calcule la nouvelle brosse tournée. - Calculer_quad_texture(X1,Y1, 0, 0, - X2,Y2,Brosse_Largeur-1, 0, - X3,Y3, 0,Brosse_Hauteur-1, - X4,Y4,Brosse_Largeur-1,Brosse_Hauteur-1, - New_Brosse,New_Brosse_Largeur,New_Brosse_Hauteur); - - free(Brosse); - Brosse=New_Brosse; - - Brosse_Largeur=New_Brosse_Largeur; - Brosse_Hauteur=New_Brosse_Hauteur; - - Smear_Brosse_Largeur=(Brosse_Largeur>TAILLE_MAXI_PINCEAU)?Brosse_Largeur:TAILLE_MAXI_PINCEAU; - Smear_Brosse_Hauteur=(Brosse_Hauteur>TAILLE_MAXI_PINCEAU)?Brosse_Hauteur:TAILLE_MAXI_PINCEAU; - Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Hauteur)*Smear_Brosse_Largeur); - - if (!Smear_Brosse) // On ne peut même pas allouer la brosse du smear! - { - Erreur(0); - - free(Brosse); - Brosse=(byte *)malloc(1*1); - Brosse_Hauteur=1; - Brosse_Largeur=1; - - Smear_Brosse=(byte *)malloc(TAILLE_MAXI_PINCEAU*TAILLE_MAXI_PINCEAU); - Smear_Brosse_Hauteur=TAILLE_MAXI_PINCEAU; - Smear_Brosse_Largeur=TAILLE_MAXI_PINCEAU; - } - - Brosse_Decalage_X=(Brosse_Largeur>>1); - Brosse_Decalage_Y=(Brosse_Hauteur>>1); - } - else - { - // Ici la libération de mémoire n'a pas suffit donc on remet dans l'état - // où c'etait avant. On a juste à réallouer la Smear_Brosse car il y a - // normalement la place pour elle puisque rien d'autre n'a pu être alloué - // entre temps. - Smear_Brosse=(byte *)malloc(((long)Smear_Brosse_Hauteur)*Smear_Brosse_Largeur); - Erreur(0); - } -} - - - -void Dessiner_quad_texture_preview(int X1,int Y1,int Xt1,int Yt1, - int X2,int Y2,int Xt2,int Yt2, - int X3,int Y3,int Xt3,int Yt3, - int X4,int Y4,int Xt4,int Yt4) -{ - int Xmin,Xmax,Ymin,Ymax; - int X,Y,Xt,Yt; - int Y_,Ymin_; - int Debut_X,Fin_X,Largeur,Hauteur; - float Temp; - byte Couleur; - - Xmin=Min(Min(X1,X2),Min(X3,X4)); - Xmax=Max(Max(X1,X2),Max(X3,X4)); - Ymin=Min(Min(Y1,Y2),Min(Y3,Y4)); - Ymax=Max(Max(Y1,Y2),Max(Y3,Y4)); - Hauteur=1+Ymax-Ymin; - - ScanY_Xt[0]=(float *)malloc(Hauteur*sizeof(float)); - ScanY_Xt[1]=(float *)malloc(Hauteur*sizeof(float)); - ScanY_Yt[0]=(float *)malloc(Hauteur*sizeof(float)); - ScanY_Yt[1]=(float *)malloc(Hauteur*sizeof(float)); - ScanY_X[0] =(float *)malloc(Hauteur*sizeof(float)); - ScanY_X[1] =(float *)malloc(Hauteur*sizeof(float)); - - // Remplir avec des valeurs égales à INDEFINI. - for (Y=0; YLimite_Bas) Ymax=Limite_Bas; - - for (Y_=Ymin; Y_<=Ymax; Y_++) - { - Y=Y_-Ymin_; - Debut_X=Round(ScanY_X[0][Y]); - Fin_X =Round(ScanY_X[1][Y]); - - Largeur=1+Fin_X-Debut_X; - - if (Debut_XLimite_Droite) Fin_X=Limite_Droite; - - for (X=Debut_X; X<=Fin_X; X++) - { - Temp=(float)(0.5+(float)X-ScanY_X[0][Y])/(float)Largeur; - Xt=Round((float)(ScanY_Xt[0][Y])+(Temp*(ScanY_Xt[1][Y]-ScanY_Xt[0][Y]))); - Yt=Round((float)(ScanY_Yt[0][Y])+(Temp*(ScanY_Yt[1][Y]-ScanY_Yt[0][Y]))); - - Couleur=Lit_pixel_dans_brosse(Xt,Yt); - if (Couleur!=Back_color) - Pixel_Preview(X,Y_,Couleur); } } - free(ScanY_Xt[0]); - free(ScanY_Xt[1]); - free(ScanY_Yt[0]); - free(ScanY_Yt[1]); - free(ScanY_X[0]); - free(ScanY_X[1]); -} + if (Y) + { + C=Lit_pixel_dans_ecran_feedback(X,Y-1); + Poids_total+=(Poids=Smooth_Matrice[1][0]); + R+=Poids*Principal_Palette[C].R; + V+=Poids*Principal_Palette[C].V; + B+=Poids*Principal_Palette[C].B; + } + if (Y2) + { + C=Lit_pixel_dans_ecran_feedback(X,Y+1); + Poids_total+=(Poids=Smooth_Matrice[1][2]); + R+=Poids*Principal_Palette[C].R; + V+=Poids*Principal_Palette[C].V; + B+=Poids*Principal_Palette[C].B; + } -void Tourner_brosse_preview(float Angle) -{ - short X1,Y1,X2,Y2,X3,Y3,X4,Y4; - int Debut_X,Fin_X,Debut_Y,Fin_Y; - float cosA=cos(Angle); - float sinA=sin(Angle); - - // Calcul des coordonnées des 4 coins: - // 1 2 - // 3 4 - - Debut_X=1-(Brosse_Largeur>>1); - Debut_Y=1-(Brosse_Hauteur>>1); - Fin_X=Debut_X+Brosse_Largeur-1; - Fin_Y=Debut_Y+Brosse_Hauteur-1; - - Transformer_point(Debut_X,Debut_Y, cosA,sinA, &X1,&Y1); - Transformer_point(Fin_X ,Debut_Y, cosA,sinA, &X2,&Y2); - Transformer_point(Debut_X,Fin_Y , cosA,sinA, &X3,&Y3); - Transformer_point(Fin_X ,Fin_Y , cosA,sinA, &X4,&Y4); - - X1+=Brosse_Centre_rotation_X; - Y1+=Brosse_Centre_rotation_Y; - X2+=Brosse_Centre_rotation_X; - Y2+=Brosse_Centre_rotation_Y; - X3+=Brosse_Centre_rotation_X; - Y3+=Brosse_Centre_rotation_Y; - X4+=Brosse_Centre_rotation_X; - Y4+=Brosse_Centre_rotation_Y; - - // Et maintenant on dessine la brosse tournée. - Dessiner_quad_texture_preview(X1,Y1, 0, 0, - X2,Y2,Brosse_Largeur-1, 0, - X3,Y3, 0,Brosse_Hauteur-1, - X4,Y4,Brosse_Largeur-1,Brosse_Hauteur-1); - Debut_X=Min(Min(X1,X2),Min(X3,X4)); - Fin_X=Max(Max(X1,X2),Max(X3,X4)); - Debut_Y=Min(Min(Y1,Y2),Min(Y3,Y4)); - Fin_Y=Max(Max(Y1,Y2),Max(Y3,Y4)); - UpdateRect(Debut_X,Debut_Y,Fin_X-Debut_X+1,Fin_Y-Debut_Y+1); -} + return (Poids_total)? // On regarde s'il faut éviter le 0/0. + Meilleure_couleur(Round_div(R,Poids_total), + Round_div(V,Poids_total), + Round_div(B,Poids_total)): + Lit_pixel_dans_ecran_courant(X,Y); // C'est bien l'écran courant et pas + // l'écran feedback car il s'agit de ne +} // pas modifier l'écran courant. diff --git a/graph.h b/graph.h index 6c96b843..189509ac 100644 --- a/graph.h +++ b/graph.h @@ -1,6 +1,6 @@ /* Grafx2 - The Ultimate 256-color bitmap paint program - Copyright 2007 Adrien Destugues + Copyright 2007-2008 Adrien Destugues Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) Grafx2 is free software; you can redistribute it and/or @@ -18,54 +18,15 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -void Remapper_ecran_apres_changement_couleurs_menu(void); -void Calculer_couleurs_menu_optimales(struct Composantes * Palette); - -unsigned long Memoire_libre(void); void Liste2tables(word * Liste, short Pas, byte Mode, byte * Table_inc, byte * Table_dec ); -void Num2str(dword Nombre,char * Chaine,byte Taille); -int Str2num(char * Chaine); - -short Round(float Valeur); -short Round_max(short Numerateur,short Diviseur); -short Round_div_max(short Numerateur,short Diviseur); - -int Min(int A,int B); -int Max(int A,int B); - void Transformer_point(short X, short Y, float cosA, float sinA, short * Xr, short * Yr); -void Recadrer_ecran_par_rapport_au_zoom(void); -void Calculer_split(void); -void Calculer_donnees_loupe(void); -void Calculer_limites(void); -void Calculer_coordonnees_pinceau(void); - -char* Libelle_mode(int Mode); -int Conversion_argument_mode(const char *Argument); - void Initialiser_mode_video(int Largeur, int Hauteur, int Fullscreen); -void Pixel_dans_barre_d_outil(word X,word Y,byte Couleur); -void Pixel_dans_fenetre(word X,word Y,byte Couleur); -void Encadrer_couleur_menu(byte Couleur); -void Afficher_palette_du_menu(void); -void Afficher_menu(void); -void Recadrer_palette(void); - -void Print_general(short X,short Y,char * Chaine,byte Couleur_texte,byte Couleur_fond); -void Print_dans_fenetre(short X,short Y,char * Chaine,byte Couleur_texte,byte Couleur_fond); -void Print_dans_fenetre_limite(short X,short Y,char * Chaine,byte Taille,byte Couleur_texte,byte Couleur_fond); -void Print_char_dans_fenetre(short Pos_X,short Pos_Y,unsigned char Caractere,byte Couleur_texte,byte Couleur_fond); -void Print_char_transparent_dans_fenetre(short Pos_X,short Pos_Y,unsigned char Caractere,byte Couleur); -void Print_dans_menu(char * Chaine, short Position); -void Print_coordonnees(void); -void Print_nom_fichier(void); -void Print_compteur(short X,short Y,char * Chaine,byte Couleur_texte,byte Couleur_fond); byte Aucun_effet(word X,word Y,byte Couleur); byte Effet_Shade(word X,word Y,byte Couleur); @@ -83,45 +44,14 @@ void Effacer_pinceau(short X,short Y); void Effacer_curseur(void); void Afficher_curseur(void); -byte Demande_de_confirmation(char * Message); -void Warning_message(char * Message); - -void Afficher_limites_de_l_image(void); -void Afficher_ecran(void); -void Fenetre_Afficher_cadre_general(word Pos_X,word Pos_Y,word Largeur,word Hauteur, - byte Couleur_HG,byte Couleur_BD,byte Couleur_S,byte Couleur_CHG,byte Couleur_CBD); -void Fenetre_Afficher_cadre_mono(word Pos_X,word Pos_Y,word Largeur,word Hauteur,byte Couleur); -void Fenetre_Afficher_cadre_creux(word Pos_X,word Pos_Y,word Largeur,word Hauteur); -void Fenetre_Afficher_cadre_bombe(word Pos_X,word Pos_Y,word Largeur,word Hauteur); -void Fenetre_Afficher_cadre(word Pos_X,word Pos_Y,word Largeur,word Hauteur); - -void Afficher_sprite_dans_menu(int Numero_bouton,int Numero_sprite); -void Afficher_pinceau_dans_menu(void); -void Afficher_pinceau_dans_fenetre(word X,word Y,int Numero); - -void Dessiner_zigouigoui(word X,word Y, byte Couleur, short Sens); -void Bloc_degrade_dans_fenetre(word Pos_X,word Pos_Y,word Debut_block,word Fin_block); void Redimentionner_image(word Largeur_choisie,word Hauteur_choisie); -void Fenetre_Afficher_sprite_drive(word Pos_X,word Pos_Y,byte Type); - -void Capturer_brosse(short Debut_X,short Debut_Y,short Fin_X,short Fin_Y,short Effacement); -void Rotate_90_deg(void); -void Etirer_brosse(short X1, short Y1, short X2, short Y2); -void Etirer_brosse_preview(short X1, short Y1, short X2, short Y2); -void Tourner_brosse(float Angle); -void Tourner_brosse_preview(float Angle); - -void Remap_brosse(void); -void Get_colors_from_brush(void); -void Outline_brush(void); -void Nibble_brush(void); - void Remplir(byte Couleur_de_remplissage); void Remplacer(byte Nouvelle_couleur); void Pixel_figure_Preview (word Pos_X,word Pos_Y,byte Couleur); void Pixel_figure_Preview_xor(word Pos_X,word Pos_Y,byte Couleur); +void Pixel_figure_Dans_brosse(word Pos_X,word Pos_Y,byte Couleur); void Tracer_cercle_vide_Definitif(short Centre_X,short Centre_Y,short Rayon,byte Couleur); void Tracer_cercle_vide_Preview (short Centre_X,short Centre_Y,short Rayon,byte Couleur); @@ -134,6 +64,7 @@ void Effacer_ellipse_vide_Preview (short Centre_X,short Centre_Y,short Rayon_hor void Tracer_ellipse_pleine (short Centre_X,short Centre_Y,short Rayon_horizontal,short Rayon_vertical,byte Couleur); void Rectifier_coordonnees_a_45_degres(short AX, short AY, short* BX, short* BY); +void Tracer_ligne_General(short Debut_X,short Debut_Y,short Fin_X,short Fin_Y, byte Couleur); void Tracer_ligne_Definitif (short Debut_X,short Debut_Y,short Fin_X,short Fin_Y,byte Couleur); void Tracer_ligne_Preview (short Debut_X,short Debut_Y,short Fin_X,short Fin_Y,byte Couleur); void Tracer_ligne_Preview_xor(short Debut_X,short Debut_Y,short Fin_X,short Fin_Y,byte Couleur); @@ -157,8 +88,8 @@ void Tracer_cercle_degrade (short Centre_X,short Centre_Y,short Rayon,short Ecl void Tracer_ellipse_degradee(short Centre_X,short Centre_Y,short Rayon_horizontal,short Rayon_vertical,short Eclairage_X,short Eclairage_Y); void Tracer_rectangle_degrade(short RAX,short RAY,short RBX,short RBY,short VAX,short VAY, short VBX, short VBY); +void Polyfill_General(int Vertices, short * Points, int Color); void Polyfill(int Vertices, short * Points, int Color); -void Capturer_brosse_au_lasso(int Vertices, short * Points,short Effacement); // Gestion des backups: void Download_infos_page_principal(S_Page * Page); @@ -182,8 +113,6 @@ void Remap_picture(void); #define ToWinL(l) ((l)*Menu_Facteur_X) #define ToWinH(h) ((h)*Menu_Facteur_Y) -byte Meilleure_couleur(byte Rouge,byte Vert,byte Bleu); -byte Meilleure_couleur_sans_exclusion(byte Rouge,byte Vert,byte Bleu); - -void Ligne_horizontale_XOR_Zoom(short Pos_X, short Pos_Y, short Largeur); -void Ligne_verticale_XOR_Zoom(short Pos_X, short Pos_Y, short Hauteur); +// Définition d'une fonction générique de traçage de figures: +fonction_afficheur Pixel_figure; +void Mettre_Ecran_A_Jour(short X, short Y, short Largeur, short Hauteur); diff --git a/init.c b/init.c index 6bca9541..6863a5ab 100644 --- a/init.c +++ b/init.c @@ -51,6 +51,7 @@ #include "hotkeys.h" #include "files.h" #include "setup.h" +#include "windows.h" // Ajouter un lecteur à la liste de lecteurs @@ -638,7 +639,6 @@ void Initialisation_des_boutons(void) Rien_du_tout, FAMILLE_OUTIL); -// !!! TEMPORAIRE !!! Initialiser_bouton(BOUTON_GRADRECT, 85,1, 15,15, @@ -646,15 +646,6 @@ void Initialisation_des_boutons(void) Bouton_Rectangle_degrade,Bouton_Rectangle_degrade, Rien_du_tout, FAMILLE_OUTIL); -/* - Initialiser_bouton(BOUTON_GRADRECT, - 85,1, - 15,15, - FORME_BOUTON_TRIANGLE_HAUT_GAUCHE, - Rien_du_tout,Rien_du_tout, - Rien_du_tout, - FAMILLE_OUTIL); -*/ Initialiser_bouton(BOUTON_GRADMENU, 86,2, @@ -712,15 +703,6 @@ void Initialisation_des_boutons(void) Bouton_Texte,Message_Non_disponible, Rien_du_tout, FAMILLE_INSTANTANE); -/* - Initialiser_bouton(BOUTON_TEXTE, - 123,18, - 16,16, - FORME_BOUTON_RECTANGLE, - Rien_du_tout,Rien_du_tout, - Rien_du_tout, - FAMILLE_INSTANTANE); -*/ Initialiser_bouton(BOUTON_LOUPE, 140,1, diff --git a/main.c b/main.c index 70427626..d8553be7 100644 --- a/main.c +++ b/main.c @@ -48,6 +48,8 @@ #include "io.h" #include "texte.h" #include "setup.h" +#include "windows.h" +#include "brush.h" #if defined(__WIN32__) #include diff --git a/readini.c b/readini.c index 80e98e2e..4a86b94a 100644 --- a/readini.c +++ b/readini.c @@ -27,6 +27,7 @@ #include "const.h" #include "global.h" #include "graph.h" +#include "windows.h" void Charger_INI_Clear_string(char * String) { diff --git a/saveini.c b/saveini.c index b4ab1c00..a8bfc21b 100644 --- a/saveini.c +++ b/saveini.c @@ -29,6 +29,7 @@ #include "io.h" #include "erreurs.h" #include "graph.h" +#include "divers.h" int Sauver_INI_Reach_group(FILE * Old_file,FILE * New_file,char * Buffer,char * Group) { diff --git a/shade.c b/shade.c index d6b2c407..3b1b3ab5 100644 --- a/shade.c +++ b/shade.c @@ -27,6 +27,7 @@ #include "readline.h" #include "aide.h" #include "sdlscreen.h" +#include "windows.h" void Bouton_Shade_Mode(void) { diff --git a/windows.c b/windows.c new file mode 100644 index 00000000..06584547 --- /dev/null +++ b/windows.c @@ -0,0 +1,2354 @@ +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Franck Charlet + Copyright 2007-2008 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. + +******************************************************************************** + + Graphical interface management functions (windows, menu, cursor) +*/ + +#include + +#include "windows.h" +#include "global.h" +#include "graph.h" +#include "moteur.h" +#include "divers.h" +#include "sdlscreen.h" + +// Affichage d'un pixel dans le menu (le menu doît être visible) +void Pixel_dans_barre_d_outil(word X,word Y,byte Couleur) +{ + Block(X*Menu_Facteur_X,(Y*Menu_Facteur_Y)+Menu_Ordonnee,Menu_Facteur_X,Menu_Facteur_Y,Couleur); +} + + // Affichage d'un pixel dans la fenêtre (la fenêtre doît être visible) + +void Pixel_dans_fenetre(word X,word Y,byte Couleur) +{ + Block((X*Menu_Facteur_X)+Fenetre_Pos_X,(Y*Menu_Facteur_Y)+Fenetre_Pos_Y,Menu_Facteur_X,Menu_Facteur_Y,Couleur); +} + + +// -- Affichages de différents cadres dans une fenêtre ----------------------- + + // -- Cadre général avec couleurs paramètrables -- + +void Fenetre_Afficher_cadre_general(word Pos_X,word Pos_Y,word Largeur,word Hauteur, + byte Couleur_HG,byte Couleur_BD,byte Couleur_S,byte Couleur_CHG,byte Couleur_CBD) +// Paramètres de couleurs: +// Couleur_HG =Bords Haut et Gauche +// Couleur_BD =Bords Bas et Droite +// Couleur_S =Coins Haut-Droite et Bas-Gauche +// Couleur_CHG=Coin Haut-Gauche +// Couleur_CBD=Coin Bas-Droite +{ + // Bord haut (sans les extrémités) + Block(Fenetre_Pos_X+((Pos_X+1)*Menu_Facteur_X), + Fenetre_Pos_Y+(Pos_Y*Menu_Facteur_Y), + (Largeur-2)*Menu_Facteur_X,Menu_Facteur_Y,Couleur_HG); + + // Bord bas (sans les extrémités) + Block(Fenetre_Pos_X+((Pos_X+1)*Menu_Facteur_X), + Fenetre_Pos_Y+((Pos_Y+Hauteur-1)*Menu_Facteur_Y), + (Largeur-2)*Menu_Facteur_X,Menu_Facteur_Y,Couleur_BD); + + // Bord gauche (sans les extrémités) + Block(Fenetre_Pos_X+(Pos_X*Menu_Facteur_X), + Fenetre_Pos_Y+((Pos_Y+1)*Menu_Facteur_Y), + Menu_Facteur_X,(Hauteur-2)*Menu_Facteur_Y,Couleur_HG); + + // Bord droite (sans les extrémités) + Block(Fenetre_Pos_X+((Pos_X+Largeur-1)*Menu_Facteur_X), + Fenetre_Pos_Y+((Pos_Y+1)*Menu_Facteur_Y), + Menu_Facteur_X,(Hauteur-2)*Menu_Facteur_Y,Couleur_BD); + + // Coin haut gauche + Pixel_dans_fenetre(Pos_X,Pos_Y,Couleur_CHG); + // Coin haut droite + Pixel_dans_fenetre(Pos_X+Largeur-1,Pos_Y,Couleur_S); + // Coin bas droite + Pixel_dans_fenetre(Pos_X+Largeur-1,Pos_Y+Hauteur-1,Couleur_CBD); + // Coin bas gauche + Pixel_dans_fenetre(Pos_X,Pos_Y+Hauteur-1,Couleur_S); +} + + // -- Cadre dont tout le contour est d'une seule couleur -- + +void Fenetre_Afficher_cadre_mono(word Pos_X,word Pos_Y,word Largeur,word Hauteur,byte Couleur) +{ + Fenetre_Afficher_cadre_general(Pos_X,Pos_Y,Largeur,Hauteur,Couleur,Couleur,Couleur,Couleur,Couleur); +} + + // -- Cadre creux: foncé en haut-gauche et clair en bas-droite -- + +void Fenetre_Afficher_cadre_creux(word Pos_X,word Pos_Y,word Largeur,word Hauteur) +{ + Fenetre_Afficher_cadre_general(Pos_X,Pos_Y,Largeur,Hauteur,CM_Fonce,CM_Blanc,CM_Clair,CM_Fonce,CM_Blanc); +} + + // -- Cadre bombé: clair en haut-gauche et foncé en bas-droite -- + +void Fenetre_Afficher_cadre_bombe(word Pos_X,word Pos_Y,word Largeur,word Hauteur) +{ + Fenetre_Afficher_cadre_general(Pos_X,Pos_Y,Largeur,Hauteur,CM_Blanc,CM_Fonce,CM_Clair,CM_Blanc,CM_Fonce); +} + + // -- Cadre de séparation: un cadre bombé dans un cadre creux (3D!!!) -- + +void Fenetre_Afficher_cadre(word Pos_X,word Pos_Y,word Largeur,word Hauteur) +{ + Fenetre_Afficher_cadre_creux(Pos_X,Pos_Y,Largeur,Hauteur); + Fenetre_Afficher_cadre_bombe(Pos_X+1,Pos_Y+1,Largeur-2,Hauteur-2); +} + + +//-- Affichages relatifs à la palette dans le menu --------------------------- + + // -- Affichage des couleurs courante (fore/back) de pinceau dans le menu -- + +void Afficher_foreback(void) +{ + if (Menu_visible) + { + Block((LARGEUR_MENU-17)*Menu_Facteur_X,Menu_Ordonnee+Menu_Facteur_Y,Menu_Facteur_X<<4,Menu_Facteur_Y*7,Back_color); + Block((LARGEUR_MENU-13)*Menu_Facteur_X,Menu_Ordonnee+(Menu_Facteur_Y<<1),Menu_Facteur_X<<3,Menu_Facteur_Y*5,Fore_color); + + UpdateRect((LARGEUR_MENU-17)*Menu_Facteur_X,Menu_Ordonnee+Menu_Facteur_Y,Menu_Facteur_X<<4,Menu_Facteur_Y*7); + } +} + + // -- Tracer un cadre de couleur autour de la Fore_color dans le menu -- + +void Encadrer_couleur_menu(byte Couleur) +{ + word Debut_X,Debut_Y,Fin_X,Fin_Y; + word Indice; + + if ((Fore_color>=Couleur_debut_palette) && (Fore_color>3)*Menu_Taille_couleur)*Menu_Facteur_X; + Debut_Y=Menu_Ordonnee+((1+(((Fore_color-Couleur_debut_palette)&7)<<2))*Menu_Facteur_Y); + + Block(Debut_X,Debut_Y,(Menu_Taille_couleur+1)*Menu_Facteur_X,Menu_Facteur_Y,Couleur); + Block(Debut_X,Debut_Y+(Menu_Facteur_Y<<2),(Menu_Taille_couleur+1)*Menu_Facteur_X,Menu_Facteur_Y,Couleur); + + Block(Debut_X,Debut_Y+Menu_Facteur_Y,Menu_Facteur_X,Menu_Facteur_Y*3,Couleur); + Block(Debut_X+(Menu_Taille_couleur*Menu_Facteur_X),Debut_Y+Menu_Facteur_Y,Menu_Facteur_X,Menu_Facteur_Y*3,Couleur); + } + else + { + if (Couleur==CM_Noir) + { + Debut_X=(LARGEUR_MENU+1+((Fore_color-Couleur_debut_palette)>>3)*Menu_Taille_couleur)*Menu_Facteur_X; + Debut_Y=Menu_Ordonnee+((2+(((Fore_color-Couleur_debut_palette)&7)<<2))*Menu_Facteur_Y); + + Block(Debut_X,Debut_Y,Menu_Taille_couleur*Menu_Facteur_X, + Menu_Facteur_Y<<2,Fore_color); + + UpdateRect(Debut_X,Debut_Y,Menu_Taille_couleur*Menu_Facteur_X,Menu_Facteur_Y*4); // TODO On met à jour toute la palette... peut mieux faire + } + else + { + Debut_X=LARGEUR_MENU+1+((Fore_color-Couleur_debut_palette)>>3)*Menu_Taille_couleur; + Debut_Y=2+(((Fore_color-Couleur_debut_palette)&7)<<2); + + Fin_X=Debut_X+Menu_Taille_couleur-1; + Fin_Y=Debut_Y+3; + + for (Indice=Debut_X; Indice<=Fin_X; Indice++) + Block(Indice*Menu_Facteur_X,Menu_Ordonnee+(Debut_Y*Menu_Facteur_Y), + Menu_Facteur_X,Menu_Facteur_Y, + ((Indice+Debut_Y)&1)?CM_Blanc:CM_Noir); + + for (Indice=Debut_Y+1; Indice>3)*Menu_Taille_couleur)*Menu_Facteur_X, + Menu_Ordonnee+((2+((Couleur&7)<<2))*Menu_Facteur_Y), + (Menu_Taille_couleur-1)*Menu_Facteur_X, + Menu_Facteur_Y*3, + Couleur_debut_palette+Couleur); + else + for (Couleur=0;Couleur<64;Couleur++) + Block((LARGEUR_MENU+1+(Couleur>>3)*Menu_Taille_couleur)*Menu_Facteur_X, + Menu_Ordonnee+((2+((Couleur&7)<<2))*Menu_Facteur_Y), + Menu_Taille_couleur*Menu_Facteur_X, + Menu_Facteur_Y<<2, + Couleur_debut_palette+Couleur); + + Encadrer_couleur_menu(CM_Blanc); + UpdateRect(LARGEUR_MENU*Menu_Facteur_X,Menu_Ordonnee,Largeur_ecran-(LARGEUR_MENU*Menu_Facteur_X),(HAUTEUR_MENU-9)*Menu_Facteur_Y); + } +} + + // -- Recalculer l'origine de la palette dans le menu pour rendre la + // Fore_color visible -- + +void Recadrer_palette(void) +{ + byte Ancienne_couleur=Couleur_debut_palette; + + if (Fore_color=Couleur_debut_palette+64) + Couleur_debut_palette+=8; + } + if (Ancienne_couleur!=Couleur_debut_palette) + Afficher_palette_du_menu(); +} + + + + // -- Afficher tout le menu -- + +void Afficher_menu(void) +{ + word Pos_X; + word Pos_Y; + char Chaine[4]; + + + if (Menu_visible) + { + // Affichage du sprite du menu + for (Pos_Y=0;Pos_Y=Principal_X_Zoom) )) + { + if ( (Operation_en_cours!=OPERATION_PIPETTE) + && (Operation_en_cours!=OPERATION_REMPLACER) ) + Print_dans_menu("X: Y: ",0); + else + { + Print_dans_menu("X: Y: ( )",0); + Num2str(Pipette_Couleur,Chaine,3); + Print_dans_menu(Chaine,20); + Print_general(170*Menu_Facteur_X,Menu_Ordonnee_Texte," ",0,Pipette_Couleur); + } + Print_coordonnees(); + } + Print_nom_fichier(); + } + UpdateRect(0,Menu_Ordonnee,Largeur_ecran,HAUTEUR_MENU*Menu_Facteur_Y); // on met toute la largur à jour, ça inclut la palette et la zone d'étant avec le nom du fichier + } +} + +// -- Affichage de texte ----------------------------------------------------- + + // -- Afficher une chaîne n'importe où à l'écran -- + +void Print_general(short X,short Y,char * Chaine,byte Couleur_texte,byte Couleur_fond) +{ + word Indice; + int Pos_X; + int Pos_Y; + byte *Caractere; + short Reel_X; + short Reel_Y; + byte Repeat_Menu_Facteur_X; + byte Repeat_Menu_Facteur_Y; + + Reel_Y=Y; + for (Pos_Y=0;Pos_Y<8;Pos_Y++) + { + Reel_X=0; // Position dans le buffer + for (Indice=0;Chaine[Indice]!='\0';Indice++) + { + // Pointeur sur le premier pixel du caractère + Caractere=Fonte+(((unsigned char)Chaine[Indice])<<6); + for (Pos_X=0;Pos_X<8<<3;Pos_X+=1<<3) + for (Repeat_Menu_Facteur_X=0;Repeat_Menu_Facteur_X Taille) + { + Chaine_affichee[Taille-1]=CARACTERE_SUSPENSION; + } + Print_dans_fenetre(X, Y, Chaine_affichee, Couleur_texte, Couleur_fond); +} + + // -- Afficher une chaîne dans une fenêtre -- + +void Print_dans_fenetre(short X,short Y,char * Chaine,byte Couleur_texte,byte Couleur_fond) +{ + Print_general((X*Menu_Facteur_X)+Fenetre_Pos_X, + (Y*Menu_Facteur_Y)+Fenetre_Pos_Y, + Chaine,Couleur_texte,Couleur_fond); + UpdateRect(X*Menu_Facteur_X+Fenetre_Pos_X,Y*Menu_Facteur_Y+Fenetre_Pos_Y,8*Menu_Facteur_X*strlen(Chaine),8*Menu_Facteur_Y); +} + + // -- Afficher une chaîne dans le menu -- + +void Print_dans_menu(char * Chaine, short Position) +{ + Print_general((18+(Position<<3))*Menu_Facteur_X,Menu_Ordonnee_Texte,Chaine,CM_Noir,CM_Clair); + UpdateRect((18+(Position<<3))*Menu_Facteur_X,Menu_Ordonnee_Texte,strlen(Chaine)*8*Menu_Facteur_X,8*Menu_Facteur_Y); +} + + // -- Afficher les coordonnées du pinceau dans le menu -- + +// Note : cette fonction n'affiche que les chiffres, pas les X: Y: qui sont dans la gestion principale, car elle est apellée très souvent. +void Print_coordonnees(void) +{ + char Tempo[5]; + + if (Menu_visible) + { + if ( (Operation_en_cours==OPERATION_PIPETTE) + || (Operation_en_cours==OPERATION_REMPLACER) ) + { + if ( (Pinceau_X>=0) && (Pinceau_Y>=0) + && (Pinceau_X12) + { + Nom_affiche[11]=CARACTERE_SUSPENSION; + Taille_nom = 12; + } + + Block((LARGEUR_MENU+2+((Menu_Taille_couleur-12)<<3))*Menu_Facteur_X, + Menu_Ordonnee_Texte,Menu_Facteur_X*96,Menu_Facteur_Y<<3,CM_Clair); + + Debut_X=LARGEUR_MENU+2+((Menu_Taille_couleur-Taille_nom)<<3); + + Print_general(Debut_X*Menu_Facteur_X,Menu_Ordonnee_Texte,Nom_affiche,CM_Noir,CM_Clair); + } +} + +// Fonction d'affichage d'une chaine numérique avec une fonte très fine +// Spécialisée pour les compteurs RGB +void Print_compteur(short X,short Y,char * Chaine,byte Couleur_texte,byte Couleur_fond) +{ + // Macros pour écrire des litteraux binaires. + // Ex: Ob(11110000) == 0xF0 + #define Ob(x) ((unsigned)Ob_(0 ## x ## uL)) + #define Ob_(x) ((x & 1) | (x >> 2 & 2) | (x >> 4 & 4) | (x >> 6 & 8) | \ + (x >> 8 & 16) | (x >> 10 & 32) | (x >> 12 & 64) | (x >> 14 & 128)) + + byte Caractere[14][8] = { + { // 0 + Ob(00011100), + Ob(00110110), + Ob(00110110), + Ob(00110110), + Ob(00110110), + Ob(00110110), + Ob(00110110), + Ob(00011100) + }, + { // 1 + Ob(00001100), + Ob(00011100), + Ob(00111100), + Ob(00001100), + Ob(00001100), + Ob(00001100), + Ob(00001100), + Ob(00001100) + }, + { // 2 + Ob(00011100), + Ob(00110110), + Ob(00000110), + Ob(00000110), + Ob(00000110), + Ob(00001100), + Ob(00011000), + Ob(00111110) + }, + { // 3 + Ob(00011100), + Ob(00110110), + Ob(00000110), + Ob(00001100), + Ob(00000110), + Ob(00000110), + Ob(00110110), + Ob(00011100) + }, + { // 4 + Ob(00001100), + Ob(00001100), + Ob(00011000), + Ob(00011000), + Ob(00110000), + Ob(00110100), + Ob(00111110), + Ob(00000100) + }, + { // 5 + Ob(00111110), + Ob(00110000), + Ob(00110000), + Ob(00111100), + Ob(00000110), + Ob(00000110), + Ob(00110110), + Ob(00011100) + }, + { // 6 + Ob(00011100), + Ob(00110110), + Ob(00110000), + Ob(00111100), + Ob(00110110), + Ob(00110110), + Ob(00110110), + Ob(00011100) + }, + { // 7 + Ob(00111110), + Ob(00000110), + Ob(00000110), + Ob(00001100), + Ob(00011000), + Ob(00011000), + Ob(00011000), + Ob(00011000) + }, + { // 8 + Ob(00011100), + Ob(00110110), + Ob(00110110), + Ob(00011100), + Ob(00110110), + Ob(00110110), + Ob(00110110), + Ob(00011100) + }, + { // 9 + Ob(00011100), + Ob(00110110), + Ob(00110110), + Ob(00011110), + Ob(00000110), + Ob(00000110), + Ob(00110110), + Ob(00011100) + }, + { // (espace) + Ob(00000000), + Ob(00000000), + Ob(00000000), + Ob(00000000), + Ob(00000000), + Ob(00000000), + Ob(00000000), + Ob(00000000) + }, + { // + + Ob(00000000), + Ob(00001000), + Ob(00001000), + Ob(00111110), + Ob(00001000), + Ob(00001000), + Ob(00000000), + Ob(00000000) + }, + { // - + Ob(00000000), + Ob(00000000), + Ob(00000000), + Ob(00111110), + Ob(00000000), + Ob(00000000), + Ob(00000000), + Ob(00000000) + }, + { // +- + Ob(00001000), + Ob(00001000), + Ob(00111110), + Ob(00001000), + Ob(00001000), + Ob(00000000), + Ob(00111110), + Ob(00000000) + } }; + + word Indice; + short Pos_X; + short Pos_Y; + for (Indice=0;Chaine[Indice]!='\0';Indice++) + { + int Numero_car; + switch(Chaine[Indice]) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + Numero_car=Chaine[Indice]-'0'; + break; + case ' ': + default: + Numero_car=10; + break; + case '+': + Numero_car=11; + break; + case '-': + Numero_car=12; + break; + case '±': + Numero_car=13; + break; + } + for (Pos_Y=0;Pos_Y<8;Pos_Y++) + { + for (Pos_X=0;Pos_X<6;Pos_X++) + { + byte Couleur = (Caractere[Numero_car][Pos_Y] & (1 << (6-Pos_X))) ? Couleur_texte:Couleur_fond; + Pixel_dans_fenetre(X+(Indice*6+Pos_X),Y+Pos_Y,Couleur); + } + } + } + UpdateRect(Fenetre_Pos_X+X*Menu_Facteur_X,Fenetre_Pos_Y+Y*Menu_Facteur_Y,strlen(Chaine)*Menu_Facteur_X*6,8*Menu_Facteur_Y); +} + + + +//---- Fenêtre demandant de confirmer une action et renvoyant la réponse ----- +byte Demande_de_confirmation(char * Message) +{ + short Bouton_clicke; + word Largeur_de_la_fenetre; + + Largeur_de_la_fenetre=(strlen(Message)<<3)+20; + + if (Largeur_de_la_fenetre<120) + Largeur_de_la_fenetre=120; + + Ouvrir_fenetre(Largeur_de_la_fenetre,60,"Confirmation"); + + Print_dans_fenetre((Largeur_de_la_fenetre>>1)-(strlen(Message)<<2),20,Message,CM_Noir,CM_Clair); + + Fenetre_Definir_bouton_normal((Largeur_de_la_fenetre/3)-20 ,37,40,14,"Yes",1,1,SDLK_y); // 1 + Fenetre_Definir_bouton_normal(((Largeur_de_la_fenetre<<1)/3)-20,37,40,14,"No" ,1,1,SDLK_n); // 2 + + UpdateRect(Fenetre_Pos_X,Fenetre_Pos_Y,Menu_Facteur_X*Largeur_de_la_fenetre,Menu_Facteur_Y*60); + + Afficher_curseur(); + + do + { + Bouton_clicke=Fenetre_Bouton_clicke(); + if (Touche==SDLK_RETURN) Bouton_clicke=1; + if (Touche==SDLK_ESCAPE) Bouton_clicke=2; + } + while (Bouton_clicke<=0); + + Fermer_fenetre(); + Afficher_curseur(); + + return (Bouton_clicke==1)? 1 : 0; +} + + + +//---- Fenêtre avertissant de quelque chose et attendant un click sur OK ----- +void Warning_message(char * Message) +{ + short Bouton_clicke; + word Largeur_de_la_fenetre; + + Largeur_de_la_fenetre=(strlen(Message)<<3)+20; + if (Largeur_de_la_fenetre<120) + Largeur_de_la_fenetre=120; + + Ouvrir_fenetre(Largeur_de_la_fenetre,60,"Warning!"); + + Print_dans_fenetre((Largeur_de_la_fenetre>>1)-(strlen(Message)<<2),20,Message,CM_Noir,CM_Clair); + Fenetre_Definir_bouton_normal((Largeur_de_la_fenetre>>1)-20 ,37,40,14,"OK",1,1,SDLK_RETURN); // 1 + UpdateRect(Fenetre_Pos_X,Fenetre_Pos_Y,Menu_Facteur_X*Largeur_de_la_fenetre,Menu_Facteur_Y*60); + Afficher_curseur(); + + do + Bouton_clicke=Fenetre_Bouton_clicke(); + while ((Bouton_clicke<=0) && (Touche!=SDLK_ESCAPE) && (Touche!=SDLK_o)); + + Fermer_fenetre(); + Afficher_curseur(); +} + + + + // -- Redessiner le sprite d'un bouton dans le menu -- + +void Afficher_sprite_dans_menu(int Numero_bouton,int Numero_sprite) +{ + word Pos_X; + word Pos_Y; + word Pos_menu_X; + word Pos_menu_Y; + byte Couleur; + + for (Pos_Y=0,Pos_menu_Y=Bouton[Numero_bouton].Decalage_Y+1;Pos_Y à 64 lignes fct(Menu_Facteur) + word Nb_couleurs =(Debut_block<=Fin_block)?Fin_block-Debut_block+1:Debut_block-Fin_block+1; + word Ligne_en_cours=(Debut_block<=Fin_block)?0:Total_lignes-1; + + word Debut_X =Fenetre_Pos_X+(Menu_Facteur_X*Pos_X); + word Largeur_ligne =Menu_Facteur_X<<4; // <=> à 16 pixels fct(Menu_Facteur) + + word Debut_Y =Fenetre_Pos_Y+(Menu_Facteur_Y*Pos_Y); + word Fin_Y =Debut_Y+Total_lignes; + word Indice; + + if (Debut_block>Fin_block) + { + Indice=Debut_block; + Debut_block=Fin_block; + Fin_block=Indice; + } + + for (Indice=Debut_Y;Indice>3)*Menu_Taille_couleur)*Menu_Facteur_X; + Debut_Y=Menu_Ordonnee_avant_fenetre+((2+((Couleur&7)<<2))*Menu_Facteur_Y); + Fin_X=Debut_X+Largeur; + Fin_Y=Debut_Y+Hauteur; + + // On affiche le bloc en entier si on peut, sinon on le découpe autour + // de la fenêtre. + if ( (Debut_Y>=Coin_Y) || (Fin_X<=Fenetre_Pos_X) || (Debut_X>=Coin_X) ) + Block(Debut_X,Debut_Y,Largeur,Hauteur,Vraie_couleur); + else + { + + if (Debut_X>=Fenetre_Pos_X) + { + if ( (Fin_X>Coin_X) || (Fin_Y>Coin_Y) ) + { + if ( (Fin_X>Coin_X) && (Fin_Y>Coin_Y) ) + { + Block(Coin_X,Debut_Y,Fin_X-Coin_X,Coin_Y-Debut_Y,Vraie_couleur); + Block(Debut_X,Coin_Y,Largeur,Fin_Y-Coin_Y,Vraie_couleur); + } + else + { + if (Fin_Y>Coin_Y) + Block(Debut_X,Coin_Y,Largeur,Fin_Y-Coin_Y,Vraie_couleur); + else + Block(Coin_X,Debut_Y,Fin_X-Coin_X,Hauteur,Vraie_couleur); + } + } + } + else + { + if (Fin_XCoin_Y) + { + Block(Debut_X,Debut_Y,Fenetre_Pos_X-Debut_X,Coin_Y-Debut_Y,Vraie_couleur); + Block(Debut_X,Coin_Y,Largeur,Fin_Y-Coin_Y,Vraie_couleur); + } + else + Block(Debut_X,Debut_Y,Fenetre_Pos_X-Debut_X,Hauteur,Vraie_couleur); + } + else + { + if (Fin_Y>Coin_Y) + { + Block(Debut_X,Debut_Y,Fenetre_Pos_X-Debut_X,Coin_Y-Debut_Y,Vraie_couleur); + Block(Coin_X,Debut_Y,Fin_X-Coin_X,Coin_Y-Debut_Y,Vraie_couleur); + Block(Debut_X,Coin_Y,Largeur,Fin_Y-Coin_Y,Vraie_couleur); + } + else + { + Block(Debut_X,Debut_Y,Fenetre_Pos_X-Debut_X,Hauteur,Vraie_couleur); + Block(Coin_X,Debut_Y,Fin_X-Coin_X,Hauteur,Vraie_couleur); + } + } + } + } + { + // Affichage du bloc directement dans le "buffer de fond" de la fenetre. + // Cela permet au bloc de couleur d'apparaitre si on déplace la fenetre. + short Pos_X; + short Pos_Y; + short Deb_X; // besoin d'une variable signée + short Deb_Y; // besoin d'une variable signée + // Attention aux unités + Deb_X = ((short)Debut_X - (short)Fenetre_Pos_X); + Deb_Y = ((short)Debut_Y - (short)Fenetre_Pos_Y); + + for (Pos_Y=Deb_Y;Pos_Y<(Deb_Y+Hauteur)&&Pos_Y=0&&Pos_Y>=0) + Pixel_fond(Pos_X,Pos_Y,Vraie_couleur); + } + } + } + UpdateRect(LARGEUR_MENU*Menu_Facteur_X,Menu_Ordonnee_avant_fenetre,Largeur_ecran-(LARGEUR_MENU*Menu_Facteur_X),(HAUTEUR_MENU-9)*Menu_Facteur_Y); +} + +// -------- Calcul des bornes de la partie d'image visible à l'écran --------- +void Calculer_limites(void) +/* + Avant l'appel à cette fonction, les données de la loupe doivent être à jour. +*/ +{ + if (Loupe_Mode) + { + // -- Calcul des limites de la partie non zoomée de l'image -- + Limite_Haut =Principal_Decalage_Y; + Limite_Gauche=Principal_Decalage_X; + Limite_visible_Bas =Limite_Haut+Menu_Ordonnee-1; + Limite_visible_Droite=Limite_Gauche+Principal_Split-1; + + if (Limite_visible_Bas>=Principal_Hauteur_image) + Limite_Bas=Principal_Hauteur_image-1; + else + Limite_Bas=Limite_visible_Bas; + + if (Limite_visible_Droite>=Principal_Largeur_image) + Limite_Droite=Principal_Largeur_image-1; + else + Limite_Droite=Limite_visible_Droite; + + // -- Calcul des limites de la partie zoomée de l'image -- + Limite_Haut_Zoom =Loupe_Decalage_Y; + Limite_Gauche_Zoom=Loupe_Decalage_X; + Limite_visible_Bas_Zoom =Limite_Haut_Zoom+Loupe_Hauteur-1; + Limite_visible_Droite_Zoom=Limite_Gauche_Zoom+Loupe_Largeur-1; + + if (Limite_visible_Bas_Zoom>=Principal_Hauteur_image) + Limite_Bas_Zoom=Principal_Hauteur_image-1; + else + Limite_Bas_Zoom=Limite_visible_Bas_Zoom; + + if (Limite_visible_Droite_Zoom>=Principal_Largeur_image) + Limite_Droite_Zoom=Principal_Largeur_image-1; + else + Limite_Droite_Zoom=Limite_visible_Droite_Zoom; + } + else + { + // -- Calcul des limites de la partie visible de l'image -- + Limite_Haut =Principal_Decalage_Y; + Limite_Gauche=Principal_Decalage_X; + Limite_visible_Bas =Limite_Haut+(Menu_visible?Menu_Ordonnee:Hauteur_ecran)-1; // A REVOIR POUR SIMPLIFICATION + Limite_visible_Droite=Limite_Gauche+Largeur_ecran-1; + + if (Limite_visible_Bas>=Principal_Hauteur_image) + Limite_Bas=Principal_Hauteur_image-1; + else + Limite_Bas=Limite_visible_Bas; + + if (Limite_visible_Droite>=Principal_Largeur_image) + Limite_Droite=Principal_Largeur_image-1; + else + Limite_Droite=Limite_visible_Droite; + } +} + + +// -- Calculer les coordonnées du pinceau en fonction du snap et de la loupe - +void Calculer_coordonnees_pinceau(void) +{ + if ((Loupe_Mode) && (Mouse_X>=Principal_X_Zoom)) + { + Pinceau_X=((Mouse_X-Principal_X_Zoom)/Loupe_Facteur)+Loupe_Decalage_X; + Pinceau_Y=(Mouse_Y/Loupe_Facteur)+Loupe_Decalage_Y; + } + else + { + Pinceau_X=Mouse_X+Principal_Decalage_X; + Pinceau_Y=Mouse_Y+Principal_Decalage_Y; + } + + if (Snap_Mode) + { + Pinceau_X=(((Pinceau_X+(Snap_Largeur>>1)-Snap_Decalage_X)/Snap_Largeur)*Snap_Largeur)+Snap_Decalage_X; + Pinceau_Y=(((Pinceau_Y+(Snap_Hauteur>>1)-Snap_Decalage_Y)/Snap_Hauteur)*Snap_Hauteur)+Snap_Decalage_Y; + } +} + + + +// -- Affichage de la limite de l'image ------------------------------------- +void Afficher_limites_de_l_image(void) +{ + short Debut; + short Pos; + short Fin; + byte Droite_visible; + byte Bas_visible; + short Ancienne_Limite_Zoom; + + Droite_visible=Principal_Largeur_image<((Loupe_Mode)?Principal_Split:Largeur_ecran); + Bas_visible =Principal_Hauteur_imagePrincipal_Split) + { + Principal_Decalage_X=Loupe_Decalage_X+(Loupe_Largeur>>1) + -(Principal_Split>>1); + if (Principal_Decalage_X<0) + Principal_Decalage_X=0; + else + if (Principal_Largeur_imageMenu_Ordonnee) + { + Principal_Decalage_Y=Loupe_Decalage_Y+(Loupe_Hauteur>>1) + -(Menu_Ordonnee>>1); + if (Principal_Decalage_Y<0) + Principal_Decalage_Y=0; + else + if (Principal_Hauteur_image>1)-X_theorique)/Loupe_Facteur)*Loupe_Facteur); + Principal_Split=Principal_X_Zoom-(Menu_Facteur_X*LARGEUR_BARRE_SPLIT); + + // Correction en cas de débordement sur la gauche + while (Principal_Split*(Loupe_Facteur+1)=X_theorique) + { + Principal_Split-=Loupe_Facteur; + Principal_X_Zoom-=Loupe_Facteur; + } +} + + + +// -------------------- Calcul des information de la loupe ------------------- +void Calculer_donnees_loupe(void) +/* + Après modification des données de la loupe, il faut recalculer les limites. +*/ +{ + Calculer_split(); + + Loupe_Largeur=(Largeur_ecran-Principal_X_Zoom)/Loupe_Facteur; + + Loupe_Hauteur=Menu_Ordonnee/Loupe_Facteur; + if (Menu_Ordonnee%Loupe_Facteur) + Loupe_Hauteur++; + + if (Loupe_Mode && Loupe_Decalage_X) + { + if (Principal_Largeur_image>1); + Centre_Y=Loupe_Decalage_Y+(Loupe_Hauteur>>1); + + Loupe_Facteur=FACTEUR_ZOOM[Indice_facteur]; + Table_mul_facteur_zoom=TABLE_ZOOM[Indice_facteur]; + Calculer_donnees_loupe(); + + if (Loupe_Mode) + { + // Recalculer le décalage de la loupe + // Centrage "brut" de lécran par rapport à la loupe + Loupe_Decalage_X=Centre_X-(Loupe_Largeur>>1); + Loupe_Decalage_Y=Centre_Y-(Loupe_Hauteur>>1); + // Correction en cas de débordement de l'image + if (Loupe_Decalage_X+Loupe_Largeur>Principal_Largeur_image) + Loupe_Decalage_X=Principal_Largeur_image-Loupe_Largeur; + if (Loupe_Decalage_Y+Loupe_Hauteur>Principal_Hauteur_image) + Loupe_Decalage_Y=Principal_Hauteur_image-Loupe_Hauteur; + if (Loupe_Decalage_X<0) + Loupe_Decalage_X=0; + if (Loupe_Decalage_Y<0) + Loupe_Decalage_Y=0; + + Recadrer_ecran_par_rapport_au_zoom(); + + Pixel_Preview=Pixel_Preview_Loupe; + + } + else + Pixel_Preview=Pixel_Preview_Normal; + + Calculer_limites(); + Calculer_coordonnees_pinceau(); +} + + + + // -- Afficher la barre de séparation entre les parties zoomées ou non en + // mode Loupe -- + +void Afficher_barre_de_split(void) +{ + // Partie grise du milieu + Block(Principal_Split+(Menu_Facteur_X<<1),Menu_Facteur_Y, + (LARGEUR_BARRE_SPLIT-4)*Menu_Facteur_X, + Menu_Ordonnee-(Menu_Facteur_Y<<1),CM_Clair); + + // Barre noire de gauche + Block(Principal_Split,0,Menu_Facteur_X,Menu_Ordonnee,CM_Noir); + + // Barre noire de droite + Block(Principal_X_Zoom-Menu_Facteur_X,0,Menu_Facteur_X,Menu_Ordonnee,CM_Noir); + + // Bord haut (blanc) + Block(Principal_Split+Menu_Facteur_X,0, + (LARGEUR_BARRE_SPLIT-3)*Menu_Facteur_X,Menu_Facteur_Y,CM_Blanc); + + // Bord gauche (blanc) + Block(Principal_Split+Menu_Facteur_X,Menu_Facteur_Y, + Menu_Facteur_X,(Menu_Ordonnee-(Menu_Facteur_Y<<1)),CM_Blanc); + + // Bord droite (gris foncé) + Block(Principal_X_Zoom-(Menu_Facteur_X<<1),Menu_Facteur_Y, + Menu_Facteur_X,(Menu_Ordonnee-(Menu_Facteur_Y<<1)),CM_Fonce); + + // Bord bas (gris foncé) + Block(Principal_Split+(Menu_Facteur_X<<1),Menu_Ordonnee-Menu_Facteur_Y, + (LARGEUR_BARRE_SPLIT-3)*Menu_Facteur_X,Menu_Facteur_Y,CM_Fonce); + + // Coin bas gauche + Block(Principal_Split+Menu_Facteur_X,Menu_Ordonnee-Menu_Facteur_Y, + Menu_Facteur_X,Menu_Facteur_Y,CM_Clair); + // Coin haut droite + Block(Principal_X_Zoom-(Menu_Facteur_X<<1),0, + Menu_Facteur_X,Menu_Facteur_Y,CM_Clair); + + UpdateRect(Principal_Split,0,LARGEUR_BARRE_SPLIT*Menu_Facteur_X,Menu_Ordonnee); // On réaffiche toute la partie à gauche du split, ce qui permet d'effacer son ancienne position +} + + + +// -- Fonctions de manipulation du curseur ----------------------------------- + + + // -- Afficher une barre horizontale XOR zoomée + +void Ligne_horizontale_XOR_Zoom(short Pos_X, short Pos_Y, short Largeur) +{ + short Pos_X_reelle=Principal_X_Zoom+(Pos_X-Loupe_Decalage_X)*Loupe_Facteur; + short Pos_Y_reelle=(Pos_Y-Loupe_Decalage_Y)*Loupe_Facteur; + short Largeur_reelle=Largeur*Loupe_Facteur; + short Pos_Y_Fin=(Pos_Y_reelle+Loupe_Facteur=Principal_X_Zoom) ) ) + || (Fenetre) || (Forme_curseur==FORME_CURSEUR_SABLIER) ) + Forme=Forme_curseur; + else + Forme=FORME_CURSEUR_FLECHE; + + switch(Forme) + { + case FORME_CURSEUR_CIBLE : + if (!Cacher_pinceau) + Afficher_pinceau(Pinceau_X,Pinceau_Y,Fore_color,1); + if (!Cacher_curseur) + { + if (Config.Curseur==1) + { + Debut_Y=(Mouse_Y<6)?6-Mouse_Y:0; + if (Debut_Y<4) + Ligne_verticale_XOR (Mouse_X,Mouse_Y+Debut_Y-6,4-Debut_Y); + + Debut_X=(Mouse_X<6)?(short)6-Mouse_X:0; + if (Debut_X<4) + Ligne_horizontale_XOR(Mouse_X+Debut_X-6,Mouse_Y,4-Debut_X); + + Fin_X=(Mouse_X+7>Largeur_ecran)?Mouse_X+7-Largeur_ecran:0; + if (Fin_X<4) + Ligne_horizontale_XOR(Mouse_X+3,Mouse_Y,4-Fin_X); + + Fin_Y=(Mouse_Y+7>Hauteur_ecran)?Mouse_Y+7-Hauteur_ecran:0; + if (Fin_Y<4) + Ligne_verticale_XOR (Mouse_X,Mouse_Y+3,4-Fin_Y); + + UpdateRect(Mouse_X+Debut_X-6,Mouse_Y+Debut_Y-6,12-Fin_X,12-Fin_Y); + } + else + { + Temp=(Config.Curseur)?FORME_CURSEUR_CIBLE_FINE:FORME_CURSEUR_CIBLE; + Debut_X=Mouse_X-Curseur_Decalage_X[Temp]; + Debut_Y=Mouse_Y-Curseur_Decalage_Y[Temp]; + + for (Pos_X=Debut_X,Compteur_X=0;Compteur_X<15;Pos_X++,Compteur_X++) + { + if( Pos_X < 0 ) continue; + for (Pos_Y=Debut_Y,Compteur_Y=0;Compteur_Y<15;Pos_Y++,Compteur_Y++) + { + if( Pos_Y < 0 ) continue; + Couleur=SPRITE_CURSEUR[Temp][Compteur_Y][Compteur_X]; + FOND_CURSEUR[Compteur_Y][Compteur_X]=Lit_pixel(Pos_X,Pos_Y); + if (Couleur!=CM_Trans) + Pixel(Pos_X,Pos_Y,Couleur); + if (Pos_Y > Hauteur_ecran) break; + } + if (Pos_X >= Largeur_ecran) break; + } + + UpdateRect(Max(Debut_X,0),Max(Debut_Y,0),Compteur_X,Compteur_Y); + } + } + break; + + case FORME_CURSEUR_CIBLE_PIPETTE: + if (!Cacher_pinceau) + Afficher_pinceau(Pinceau_X,Pinceau_Y,Fore_color,1); + if (!Cacher_curseur) + { + if (Config.Curseur==1) + { + // Barres formant la croix principale + + Debut_Y=(Mouse_Y<5)?5-Mouse_Y:0; + if (Debut_Y<3) + Ligne_verticale_XOR (Mouse_X,Mouse_Y+Debut_Y-5,3-Debut_Y); + + Debut_X=(Mouse_X<5)?(short)5-Mouse_X:0; + if (Debut_X<3) + Ligne_horizontale_XOR(Mouse_X+Debut_X-5,Mouse_Y,3-Debut_X); + + Fin_X=(Mouse_X+6>Largeur_ecran)?Mouse_X+6-Largeur_ecran:0; + if (Fin_X<3) + Ligne_horizontale_XOR(Mouse_X+3,Mouse_Y,3-Fin_X); + + Fin_Y=(Mouse_Y+6>Menu_Ordonnee/*Hauteur_ecran*/)?Mouse_Y+6-Menu_Ordonnee/*Hauteur_ecran*/:0; + if (Fin_Y<3) + Ligne_verticale_XOR (Mouse_X,Mouse_Y+3,3-Fin_Y); + + // Petites barres aux extrémités + + Debut_X=(!Mouse_X); + Debut_Y=(!Mouse_Y); + Fin_X=(Mouse_X>=Largeur_ecran-1); + Fin_Y=(Mouse_Y>=Menu_Ordonnee-1); + + if (Mouse_Y>5) + Ligne_horizontale_XOR(Debut_X+Mouse_X-1,Mouse_Y-6,3-(Debut_X+Fin_X)); + + if (Mouse_X>5) + Ligne_verticale_XOR (Mouse_X-6,Debut_Y+Mouse_Y-1,3-(Debut_Y+Fin_Y)); + + if (Mouse_X=0) && (Pos_X=0) && (Pos_Y=Largeur_ecran) break; + for (Pos_Y=Debut_Y,Compteur_Y=0;Compteur_Y<15;Pos_Y++,Compteur_Y++) + { + if(Pos_Y<0) continue; + if(Pos_Y>=Hauteur_ecran) break; + Couleur=SPRITE_CURSEUR[Forme][Compteur_Y][Compteur_X]; + // On sauvegarde dans FOND_CURSEUR pour restaurer plus tard + FOND_CURSEUR[Compteur_Y][Compteur_X]=Lit_pixel(Pos_X,Pos_Y); + if (Couleur!=CM_Trans) + Pixel(Pos_X,Pos_Y,Couleur); + } + } + UpdateRect(Max(Debut_X,0),Max(Debut_Y,0),Compteur_X,Compteur_Y); + break; + + case FORME_CURSEUR_CIBLE_XOR : + Pos_X=Pinceau_X-Principal_Decalage_X; + Pos_Y=Pinceau_Y-Principal_Decalage_Y; + + Compteur_X=(Loupe_Mode)?Principal_Split:Largeur_ecran; // Largeur de la barre XOR + if ((Pos_Y=Limite_Haut)) + { + Ligne_horizontale_XOR(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X); + UpdateRect(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X,1); + } + + if ((Pos_X=Limite_Gauche)) + { + Ligne_verticale_XOR(Pinceau_X-Principal_Decalage_X,0,Menu_Ordonnee); + UpdateRect(Pinceau_X-Principal_Decalage_X,0,1,Menu_Ordonnee); + } + + if (Loupe_Mode) + { + // UPDATERECT + if ((Pinceau_Y>=Limite_Haut_Zoom) && (Pinceau_Y<=Limite_visible_Bas_Zoom)) + Ligne_horizontale_XOR_Zoom(Limite_Gauche_Zoom,Pinceau_Y,Loupe_Largeur); + if ((Pinceau_X>=Limite_Gauche_Zoom) && (Pinceau_X<=Limite_visible_Droite_Zoom)) + Ligne_verticale_XOR_Zoom(Pinceau_X,Limite_Haut_Zoom,Loupe_Hauteur); + } + break; + case FORME_CURSEUR_RECTANGLE_XOR : + // !!! Cette forme ne peut pas être utilisée en mode Loupe !!! + + // Petite croix au centre + Debut_X=(Mouse_X-3); + Debut_Y=(Mouse_Y-3); + Fin_X =(Mouse_X+4); + Fin_Y =(Mouse_Y+4); + if (Debut_X<0) + Debut_X=0; + if (Debut_Y<0) + Debut_Y=0; + if (Fin_X>Largeur_ecran) + Fin_X=Largeur_ecran; + if (Fin_Y>Menu_Ordonnee) + Fin_Y=Menu_Ordonnee; + + Ligne_horizontale_XOR(Debut_X,Mouse_Y,Fin_X-Debut_X); + Ligne_verticale_XOR (Mouse_X,Debut_Y,Fin_Y-Debut_Y); + + // Grand rectangle autour + Debut_X=Mouse_X-(Loupe_Largeur>>1); + Debut_Y=Mouse_Y-(Loupe_Hauteur>>1); + if (Debut_X+Loupe_Largeur>=Limite_Droite-Principal_Decalage_X) + Debut_X=Limite_Droite-Loupe_Largeur-Principal_Decalage_X+1; + if (Debut_Y+Loupe_Hauteur>=Limite_Bas-Principal_Decalage_Y) + Debut_Y=Limite_Bas-Loupe_Hauteur-Principal_Decalage_Y+1; + if (Debut_X<0) + Debut_X=0; + if (Debut_Y<0) + Debut_Y=0; + Fin_X=Debut_X+Loupe_Largeur-1; + Fin_Y=Debut_Y+Loupe_Hauteur-1; + + Ligne_horizontale_XOR(Debut_X,Debut_Y,Loupe_Largeur); + Ligne_verticale_XOR(Debut_X,Debut_Y+1,Loupe_Hauteur-2); + Ligne_verticale_XOR( Fin_X,Debut_Y+1,Loupe_Hauteur-2); + Ligne_horizontale_XOR(Debut_X, Fin_Y,Loupe_Largeur); + + UpdateRect(Debut_X,Debut_Y,Fin_X+1-Debut_X,Fin_Y+1-Debut_Y); + + break; + default: //case FORME_CURSEUR_ROTATE_XOR : + Debut_X=1-(Brosse_Largeur>>1); + Debut_Y=1-(Brosse_Hauteur>>1); + Fin_X=Debut_X+Brosse_Largeur-1; + Fin_Y=Debut_Y+Brosse_Hauteur-1; + + if (Brosse_Centre_rotation_defini) + { + if ( (Brosse_Centre_rotation_X==Pinceau_X) + && (Brosse_Centre_rotation_Y==Pinceau_Y) ) + { + cosA=1.0; + sinA=0.0; + } + else + { + Pos_X=Pinceau_X-Brosse_Centre_rotation_X; + Pos_Y=Pinceau_Y-Brosse_Centre_rotation_Y; + cosA=(float)Pos_X/sqrt((Pos_X*Pos_X)+(Pos_Y*Pos_Y)); + sinA=sin(acos(cosA)); + if (Pos_Y>0) sinA=-sinA; + } + + Transformer_point(Debut_X,Debut_Y, cosA,sinA, &X1,&Y1); + Transformer_point(Fin_X ,Debut_Y, cosA,sinA, &X2,&Y2); + Transformer_point(Debut_X,Fin_Y , cosA,sinA, &X3,&Y3); + Transformer_point(Fin_X ,Fin_Y , cosA,sinA, &X4,&Y4); + + X1+=Brosse_Centre_rotation_X; + Y1+=Brosse_Centre_rotation_Y; + X2+=Brosse_Centre_rotation_X; + Y2+=Brosse_Centre_rotation_Y; + X3+=Brosse_Centre_rotation_X; + Y3+=Brosse_Centre_rotation_Y; + X4+=Brosse_Centre_rotation_X; + Y4+=Brosse_Centre_rotation_Y; + Pixel_figure_Preview_xor(Brosse_Centre_rotation_X,Brosse_Centre_rotation_Y,0); + Tracer_ligne_Preview_xor(Brosse_Centre_rotation_X,Brosse_Centre_rotation_Y,Pinceau_X,Pinceau_Y,0); + } + else + { + X1=X3=1-Brosse_Largeur; + Y1=Y2=Debut_Y; + X2=X4=Pinceau_X; + Y3=Y4=Fin_Y; + + X1+=Pinceau_X; + Y1+=Pinceau_Y; + Y2+=Pinceau_Y; + X3+=Pinceau_X; + Y3+=Pinceau_Y; + Y4+=Pinceau_Y; + Pixel_figure_Preview_xor(Pinceau_X-Fin_X,Pinceau_Y,0); + Tracer_ligne_Preview_xor(Pinceau_X-Fin_X,Pinceau_Y,Pinceau_X,Pinceau_Y,0); + } + + Tracer_ligne_Preview_xor(X1,Y1,X2,Y2,0); + Tracer_ligne_Preview_xor(X2,Y2,X4,Y4,0); + Tracer_ligne_Preview_xor(X4,Y4,X3,Y3,0); + Tracer_ligne_Preview_xor(X3,Y3,X1,Y1,0); + } +} + + // -- Effacer le curseur -- + +void Effacer_curseur(void) +{ + byte Forme; + int Debut_X; // int car sont parfois négatifs ! (quand on dessine sur un bord) + int Debut_Y; + short Fin_X; + short Fin_Y; + int Pos_X; + int Pos_Y; + short Compteur_X; + short Compteur_Y; + //short Fin_Compteur_X; // Position X ou s'arrête l'affichage de la brosse/pinceau + //short Fin_Compteur_Y; // Position Y ou s'arrête l'affichage de la brosse/pinceau + int Temp; + //byte Couleur; + float cosA,sinA; + short X1,Y1,X2,Y2,X3,Y3,X4,Y4; + + if ( ( (Mouse_Y=Principal_X_Zoom) ) ) + || (Fenetre) || (Forme_curseur==FORME_CURSEUR_SABLIER) ) + Forme=Forme_curseur; + else + Forme=FORME_CURSEUR_FLECHE; + + switch(Forme) + { + case FORME_CURSEUR_CIBLE : + if (!Cacher_curseur) + { + if (Config.Curseur==1) + { + Debut_Y=(Mouse_Y<6)?6-Mouse_Y:0; + if (Debut_Y<4) + Ligne_verticale_XOR (Mouse_X,Mouse_Y+Debut_Y-6,4-Debut_Y); + + Debut_X=(Mouse_X<6)?(short)6-Mouse_X:0; + if (Debut_X<4) + Ligne_horizontale_XOR(Mouse_X+Debut_X-6,Mouse_Y,4-Debut_X); + + Fin_X=(Mouse_X+7>Largeur_ecran)?Mouse_X+7-Largeur_ecran:0; + if (Fin_X<4) + Ligne_horizontale_XOR(Mouse_X+3,Mouse_Y,4-Fin_X); + + Fin_Y=(Mouse_Y+7>Hauteur_ecran)?Mouse_Y+7-Hauteur_ecran:0; + if (Fin_Y<4) + Ligne_verticale_XOR (Mouse_X,Mouse_Y+3,4-Fin_Y); + + UpdateRect(Mouse_X+Debut_X-6,Mouse_Y+Debut_Y-6,12-Fin_X,12-Fin_Y); + } + else + { + Temp=(Config.Curseur)?FORME_CURSEUR_CIBLE_FINE:FORME_CURSEUR_CIBLE; + Debut_X=Mouse_X-Curseur_Decalage_X[Temp]; + Debut_Y=Mouse_Y-Curseur_Decalage_Y[Temp]; + + for (Pos_Y=Debut_Y,Compteur_Y=0;Compteur_Y<15;Pos_Y++,Compteur_Y++) + { + if(Pos_Y>=Hauteur_ecran) break; + for (Pos_X=Debut_X,Compteur_X=0;Compteur_X<15;Pos_X++,Compteur_X++) + { + if ( (Pos_X<0) || (Pos_Y < 0)) continue; + else if (Pos_X>=Largeur_ecran) break; + Pixel(Pos_X,Pos_Y,FOND_CURSEUR[Compteur_Y][Compteur_X]); + } + } + + UpdateRect(Max(Debut_X,0),Max(Debut_Y,0),Pos_X-Debut_X,Pos_Y-Debut_Y); + } + } + if (!Cacher_pinceau) + { + Effacer_pinceau(Pinceau_X,Pinceau_Y); + } + break; + + case FORME_CURSEUR_CIBLE_PIPETTE: + if (!Cacher_curseur) + { + if (Config.Curseur==1) + { + // Barres formant la croix principale + + Debut_Y=(Mouse_Y<5)?5-Mouse_Y:0; + if (Debut_Y<3) + Ligne_verticale_XOR (Mouse_X,Mouse_Y+Debut_Y-5,3-Debut_Y); + + Debut_X=(Mouse_X<5)?(short)5-Mouse_X:0; + if (Debut_X<3) + Ligne_horizontale_XOR(Mouse_X+Debut_X-5,Mouse_Y,3-Debut_X); + + Fin_X=(Mouse_X+6>Largeur_ecran)?Mouse_X+6-Largeur_ecran:0; + if (Fin_X<3) + Ligne_horizontale_XOR(Mouse_X+3,Mouse_Y,3-Fin_X); + + Fin_Y=(Mouse_Y+6>Hauteur_ecran)?Mouse_Y+6-Hauteur_ecran:0; + if (Fin_Y<3) + Ligne_verticale_XOR (Mouse_X,Mouse_Y+3,3-Fin_Y); + + Debut_X=(!Mouse_X); + Debut_Y=(!Mouse_Y); + Fin_X=(Mouse_X>=Largeur_ecran-1); + Fin_Y=(Mouse_Y>=Menu_Ordonnee-1); + + if (Mouse_Y>5) + Ligne_horizontale_XOR(Debut_X+Mouse_X-1,Mouse_Y-6,3-(Debut_X+Fin_X)); + + if (Mouse_X>5) + Ligne_verticale_XOR (Mouse_X-6,Debut_Y+Mouse_Y-1,3-(Debut_Y+Fin_Y)); + + if (Mouse_X=0) && (Pos_X=0) && (Pos_Y=Largeur_ecran) break; + for (Pos_Y=Debut_Y,Compteur_Y=0;Compteur_Y<15;Pos_Y++,Compteur_Y++) + { + if(Pos_Y<0) continue; + if(Pos_Y>=Hauteur_ecran) break; + Pixel(Pos_X,Pos_Y,FOND_CURSEUR[Compteur_Y][Compteur_X]); + } + } + UpdateRect(Max(Debut_X,0),Max(Debut_Y,0),Compteur_X,Compteur_Y); + break; + + case FORME_CURSEUR_CIBLE_XOR : + Pos_X=Pinceau_X-Principal_Decalage_X; + Pos_Y=Pinceau_Y-Principal_Decalage_Y; + + Compteur_X=(Loupe_Mode)?Principal_Split:Largeur_ecran; // Largeur de la barre XOR + if ((Pos_Y=Limite_Haut)) + { + Ligne_horizontale_XOR(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X); + UpdateRect(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X,1); + } + + if ((Pos_X=Limite_Gauche)) + { + Ligne_verticale_XOR(Pinceau_X-Principal_Decalage_X,0,Menu_Ordonnee); + UpdateRect(Pinceau_X-Principal_Decalage_X,0,1,Menu_Ordonnee); + } + + if (Loupe_Mode) + { + // UPDATERECT + if ((Pinceau_Y>=Limite_Haut_Zoom) && (Pinceau_Y<=Limite_visible_Bas_Zoom)) + Ligne_horizontale_XOR_Zoom(Limite_Gauche_Zoom,Pinceau_Y,Loupe_Largeur); + if ((Pinceau_X>=Limite_Gauche_Zoom) && (Pinceau_X<=Limite_visible_Droite_Zoom)) + Ligne_verticale_XOR_Zoom(Pinceau_X,Limite_Haut_Zoom,Loupe_Hauteur); + } + + + break; + case FORME_CURSEUR_RECTANGLE_XOR : + // !!! Cette forme ne peut pas être utilisée en mode Loupe !!! + + // Petite croix au centre + Debut_X=(Mouse_X-3); + Debut_Y=(Mouse_Y-3); + Fin_X =(Mouse_X+4); + Fin_Y =(Mouse_Y+4); + if (Debut_X<0) + Debut_X=0; + if (Debut_Y<0) + Debut_Y=0; + if (Fin_X>Largeur_ecran) + Fin_X=Largeur_ecran; + if (Fin_Y>Menu_Ordonnee) + Fin_Y=Menu_Ordonnee; + + Ligne_horizontale_XOR(Debut_X,Mouse_Y,Fin_X-Debut_X); + Ligne_verticale_XOR (Mouse_X,Debut_Y,Fin_Y-Debut_Y); + + // Grand rectangle autour + + Debut_X=Mouse_X-(Loupe_Largeur>>1); + Debut_Y=Mouse_Y-(Loupe_Hauteur>>1); + if (Debut_X+Loupe_Largeur>=Limite_Droite-Principal_Decalage_X) + Debut_X=Limite_Droite-Loupe_Largeur-Principal_Decalage_X+1; + if (Debut_Y+Loupe_Hauteur>=Limite_Bas-Principal_Decalage_Y) + Debut_Y=Limite_Bas-Loupe_Hauteur-Principal_Decalage_Y+1; + if (Debut_X<0) + Debut_X=0; + if (Debut_Y<0) + Debut_Y=0; + Fin_X=Debut_X+Loupe_Largeur-1; + Fin_Y=Debut_Y+Loupe_Hauteur-1; + + Ligne_horizontale_XOR(Debut_X,Debut_Y,Loupe_Largeur); + Ligne_verticale_XOR(Debut_X,Debut_Y+1,Loupe_Hauteur-2); + Ligne_verticale_XOR( Fin_X,Debut_Y+1,Loupe_Hauteur-2); + Ligne_horizontale_XOR(Debut_X, Fin_Y,Loupe_Largeur); + + UpdateRect(Debut_X,Debut_Y,Fin_X+1-Debut_X,Fin_Y+1-Debut_Y); + + break; + default: //case FORME_CURSEUR_ROTATE_XOR : + Debut_X=1-(Brosse_Largeur>>1); + Debut_Y=1-(Brosse_Hauteur>>1); + Fin_X=Debut_X+Brosse_Largeur-1; + Fin_Y=Debut_Y+Brosse_Hauteur-1; + + if (Brosse_Centre_rotation_defini) + { + if ( (Brosse_Centre_rotation_X==Pinceau_X) + && (Brosse_Centre_rotation_Y==Pinceau_Y) ) + { + cosA=1.0; + sinA=0.0; + } + else + { + Pos_X=Pinceau_X-Brosse_Centre_rotation_X; + Pos_Y=Pinceau_Y-Brosse_Centre_rotation_Y; + cosA=(float)Pos_X/sqrt((Pos_X*Pos_X)+(Pos_Y*Pos_Y)); + sinA=sin(acos(cosA)); + if (Pos_Y>0) sinA=-sinA; + } + + Transformer_point(Debut_X,Debut_Y, cosA,sinA, &X1,&Y1); + Transformer_point(Fin_X ,Debut_Y, cosA,sinA, &X2,&Y2); + Transformer_point(Debut_X,Fin_Y , cosA,sinA, &X3,&Y3); + Transformer_point(Fin_X ,Fin_Y , cosA,sinA, &X4,&Y4); + + X1+=Brosse_Centre_rotation_X; + Y1+=Brosse_Centre_rotation_Y; + X2+=Brosse_Centre_rotation_X; + Y2+=Brosse_Centre_rotation_Y; + X3+=Brosse_Centre_rotation_X; + Y3+=Brosse_Centre_rotation_Y; + X4+=Brosse_Centre_rotation_X; + Y4+=Brosse_Centre_rotation_Y; + Pixel_figure_Preview_xor(Brosse_Centre_rotation_X,Brosse_Centre_rotation_Y,0); + Tracer_ligne_Preview_xor(Brosse_Centre_rotation_X,Brosse_Centre_rotation_Y,Pinceau_X,Pinceau_Y,0); + } + else + { + X1=X3=1-Brosse_Largeur; + Y1=Y2=Debut_Y; + X2=X4=Pinceau_X; + Y3=Y4=Fin_Y; + + X1+=Pinceau_X; + Y1+=Pinceau_Y; + Y2+=Pinceau_Y; + X3+=Pinceau_X; + Y3+=Pinceau_Y; + Y4+=Pinceau_Y; + Pixel_figure_Preview_xor(Pinceau_X-Fin_X,Pinceau_Y,0); + Tracer_ligne_Preview_xor(Pinceau_X-Fin_X,Pinceau_Y,Pinceau_X,Pinceau_Y,0); + } + + Tracer_ligne_Preview_xor(X1,Y1,X2,Y2,0); + Tracer_ligne_Preview_xor(X2,Y2,X4,Y4,0); + Tracer_ligne_Preview_xor(X4,Y4,X3,Y3,0); + Tracer_ligne_Preview_xor(X3,Y3,X1,Y1,0); + } +} + + + +// -- Fonction diverses d'affichage ------------------------------------------ + + // -- Reafficher toute l'image (en prenant en compte le facteur de zoom) -- + +void Afficher_ecran(void) +{ + word Largeur; + word Hauteur; + + // ---/\/\/\ Partie non zoomée: /\/\/\--- + if (Loupe_Mode) + { + if (Principal_Largeur_image or + write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef __WINDOWSH__ +#define __WINDOWSH__ + +#include "struct.h" + +void Remapper_ecran_apres_changement_couleurs_menu(void); +void Calculer_couleurs_menu_optimales(struct Composantes * Palette); + +void Recadrer_ecran_par_rapport_au_zoom(void); +void Calculer_split(void); +void Calculer_donnees_loupe(void); +void Calculer_limites(void); +void Calculer_coordonnees_pinceau(void); + +void Pixel_dans_barre_d_outil(word X,word Y,byte Couleur); +void Pixel_dans_fenetre(word X,word Y,byte Couleur); +void Encadrer_couleur_menu(byte Couleur); +void Afficher_palette_du_menu(void); +void Afficher_menu(void); +void Recadrer_palette(void); + +void Print_general(short X,short Y,char * Chaine,byte Couleur_texte,byte Couleur_fond); +void Print_dans_fenetre(short X,short Y,char * Chaine,byte Couleur_texte,byte Couleur_fond); +void Print_dans_fenetre_limite(short X,short Y,char * Chaine,byte Taille,byte Couleur_texte,byte Couleur_fond); +void Print_char_dans_fenetre(short Pos_X,short Pos_Y,unsigned char Caractere,byte Couleur_texte,byte Couleur_fond); +void Print_char_transparent_dans_fenetre(short Pos_X,short Pos_Y,unsigned char Caractere,byte Couleur); +void Print_dans_menu(char * Chaine, short Position); +void Print_coordonnees(void); +void Print_nom_fichier(void); +void Print_compteur(short X,short Y,char * Chaine,byte Couleur_texte,byte Couleur_fond); + +byte Demande_de_confirmation(char * Message); +void Warning_message(char * Message); + +void Afficher_limites_de_l_image(void); +void Afficher_ecran(void); +void Fenetre_Afficher_cadre_general(word Pos_X,word Pos_Y,word Largeur,word Hauteur, + byte Couleur_HG,byte Couleur_BD,byte Couleur_S,byte Couleur_CHG,byte Couleur_CBD); +void Fenetre_Afficher_cadre_mono(word Pos_X,word Pos_Y,word Largeur,word Hauteur,byte Couleur); +void Fenetre_Afficher_cadre_creux(word Pos_X,word Pos_Y,word Largeur,word Hauteur); +void Fenetre_Afficher_cadre_bombe(word Pos_X,word Pos_Y,word Largeur,word Hauteur); +void Fenetre_Afficher_cadre(word Pos_X,word Pos_Y,word Largeur,word Hauteur); + +void Afficher_sprite_dans_menu(int Numero_bouton,int Numero_sprite); +void Afficher_pinceau_dans_menu(void); +void Afficher_pinceau_dans_fenetre(word X,word Y,int Numero); + +void Dessiner_zigouigoui(word X,word Y, byte Couleur, short Sens); +void Bloc_degrade_dans_fenetre(word Pos_X,word Pos_Y,word Debut_block,word Fin_block); +void Fenetre_Afficher_sprite_drive(word Pos_X,word Pos_Y,byte Type); + +byte Meilleure_couleur(byte Rouge,byte Vert,byte Bleu); +byte Meilleure_couleur_sans_exclusion(byte Rouge,byte Vert,byte Bleu); + +void Ligne_horizontale_XOR_Zoom(short Pos_X, short Pos_Y, short Largeur); +void Ligne_verticale_XOR_Zoom(short Pos_X, short Pos_Y, short Hauteur); + +#endif