/* 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 // strncpy() strlen() #include "windows.h" #include "global.h" #include "graph.h" #include "moteur.h" #include "divers.h" #include "sdlscreen.h" #include "erreurs.h" // L'encapsulation tente une percée...ou un dernier combat. // Nombre de cellules réel dans la palette du menu word Menu_Cellules_X; word Palette_Cells_X() { return Menu_Cellules_X; } word Menu_Cellules_Y; word Palette_Cells_Y() { return Menu_Cellules_Y; } // Affichage d'un pixel dans le menu (le menu doit ê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 doit ê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); } // Affichage d'un rectangle dans la fenêtre (la fenêtre doit être visible) void Window_rectangle(word x_pos,word y_pos,word width,word height,byte color) { Block((x_pos*Menu_Facteur_X)+Fenetre_Pos_X,(y_pos*Menu_Facteur_Y)+Fenetre_Pos_Y,width*Menu_Facteur_X,height*Menu_Facteur_Y,color); } // -- Affichages de différents cadres dans une fenêtre ----------------------- // -- Cadre général avec couleurs paramètrables -- void Fenetre_Afficher_cadre_general(word x_pos,word y_pos,word width,word height, 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+((x_pos+1)*Menu_Facteur_X), Fenetre_Pos_Y+(y_pos*Menu_Facteur_Y), (width-2)*Menu_Facteur_X,Menu_Facteur_Y,Couleur_HG); // Bord bas (sans les extrémités) Block(Fenetre_Pos_X+((x_pos+1)*Menu_Facteur_X), Fenetre_Pos_Y+((y_pos+height-1)*Menu_Facteur_Y), (width-2)*Menu_Facteur_X,Menu_Facteur_Y,Couleur_BD); // Bord gauche (sans les extrémités) Block(Fenetre_Pos_X+(x_pos*Menu_Facteur_X), Fenetre_Pos_Y+((y_pos+1)*Menu_Facteur_Y), Menu_Facteur_X,(height-2)*Menu_Facteur_Y,Couleur_HG); // Bord droite (sans les extrémités) Block(Fenetre_Pos_X+((x_pos+width-1)*Menu_Facteur_X), Fenetre_Pos_Y+((y_pos+1)*Menu_Facteur_Y), Menu_Facteur_X,(height-2)*Menu_Facteur_Y,Couleur_BD); // Coin haut gauche Pixel_dans_fenetre(x_pos,y_pos,Couleur_CHG); // Coin haut droite Pixel_dans_fenetre(x_pos+width-1,y_pos,Couleur_S); // Coin bas droite Pixel_dans_fenetre(x_pos+width-1,y_pos+height-1,Couleur_CBD); // Coin bas gauche Pixel_dans_fenetre(x_pos,y_pos+height-1,Couleur_S); } // -- Cadre dont tout le contour est d'une seule couleur -- void Fenetre_Afficher_cadre_mono(word x_pos,word y_pos,word width,word height,byte Couleur) { Fenetre_Afficher_cadre_general(x_pos,y_pos,width,height,Couleur,Couleur,Couleur,Couleur,Couleur); } // -- Cadre creux: foncé en haut-gauche et clair en bas-droite -- void Fenetre_Afficher_cadre_creux(word x_pos,word y_pos,word width,word height) { Fenetre_Afficher_cadre_general(x_pos,y_pos,width,height,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 x_pos,word y_pos,word width,word height) { Fenetre_Afficher_cadre_general(x_pos,y_pos,width,height,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 x_pos,word y_pos,word width,word height) { Fenetre_Afficher_cadre_creux(x_pos,y_pos,width,height); Fenetre_Afficher_cadre_bombe(x_pos+1,y_pos+1,width-2,height-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; word Hauteur_cellule=32/Menu_Cellules_Y; if ((Fore_color>=Couleur_debut_palette) && (Fore_color=Couleur_debut_palette+Menu_Cellules_X*Menu_Cellules_Y) Couleur_debut_palette+=Menu_Cellules_Y; } if (Ancienne_couleur!=Couleur_debut_palette) Afficher_palette_du_menu(); } void Changer_cellules_palette() { // On initialise avec la configuration de l'utilisateur Menu_Cellules_X=Config.Palette_Cells_X; Menu_Cellules_Y=Config.Palette_Cells_Y; // Mais on sait jamais if (Menu_Cellules_X<1) Menu_Cellules_X=1; if (Menu_Cellules_Y<1) Menu_Cellules_Y=1; while (1) { Menu_Taille_couleur = ((Largeur_ecran/Menu_Facteur_X)-(LARGEUR_MENU+2)) / Menu_Cellules_X; // Si ça tient, c'est bon. Sinon, on retente avec une colonne de moins if (Menu_Taille_couleur>2) break; Menu_Cellules_X--; } // Cale Couleur_debut_palette sur un multiple de Cells_Y (arrondi inférieur) Couleur_debut_palette=Couleur_debut_palette/Menu_Cellules_Y*Menu_Cellules_Y; // Si le nombre de cellules a beaucoup augmenté et qu'on était près de // la fin, il faut reculer Couleur_debut_palette pour montrer plein // de couleurs. if ((int)Couleur_debut_palette+(Menu_Cellules_Y)*Menu_Cellules_X*2>=256) Couleur_debut_palette=255/Menu_Cellules_Y*Menu_Cellules_Y-(Menu_Cellules_X-1)*Menu_Cellules_Y; // Mise à jour de la taille du bouton dans le menu. C'est pour pas que // la bordure noire soit active. Bouton[BOUTON_CHOIX_COL].Width=(Menu_Taille_couleur*Menu_Cellules_X)-1; Bouton[BOUTON_CHOIX_COL].Height=32/Menu_Cellules_Y*Menu_Cellules_Y-1; } // Retrouve la couleur sur laquelle pointe le curseur souris. // Cette fonction suppose qu'on a déja vérifié que le curseur est dans // la zone rectangulaire du BOUTON_CHOIX_COL // La fonction renvoie -1 si on est "trop à gauche" (pas possible) // ou après la couleur 255 (Ce qui peut arriver si la palette est affichée // avec un nombre de lignes qui n'est pas une puissance de deux.) int Couleur_palette() { int Col; int line; line=(((Mouse_Y-Menu_Ordonnee)/Menu_Facteur_Y)-2)/(32/Menu_Cellules_Y); Col=Couleur_debut_palette+line+ ((((Mouse_X/Menu_Facteur_X)-(LARGEUR_MENU+1))/Menu_Taille_couleur)*Menu_Cellules_Y); if (Col<0 || Col>255) return -1; return Col; } // -- Afficher tout le menu -- void Afficher_menu(void) { word x_pos; word y_pos; char Chaine[4]; if (Menu_visible) { // Affichage du sprite du menu for (y_pos=0;y_pos=Principal_X_Zoom) )) { // Dans ces deux cas, on met dans la barre les XY courant, même s'il y a des chances que ça soit recouvert si la souris est sur un bouton (trop chiant à vérifier) 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'état avec le nom du fichier } } // -- Affichage de texte ----------------------------------------------------- // -- Afficher une chaîne n'importe où à l'écran -- void Print_general(short x,short y,const char * Chaine,byte Couleur_texte,byte Couleur_fond) { word Indice; int x_pos; int y_pos; byte *font_pixel; short Reel_X; short Reel_Y; byte Repeat_Menu_Facteur_X; byte Repeat_Menu_Facteur_Y; Reel_Y=y; for (y_pos=0;y_pos<8<<3;y_pos+=1<<3) { Reel_X=0; // Position dans le buffer for (Indice=0;Chaine[Indice]!='\0';Indice++) { // Pointeur sur le premier pixel du caractère font_pixel=Fonte+(((unsigned char)Chaine[Indice])<<6); for (x_pos=0;x_pos<8;x_pos+=1) for (Repeat_Menu_Facteur_X=0;Repeat_Menu_Facteur_X size) { Chaine_affichee[size-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,const 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(const 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 && !Curseur_dans_menu) { 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_ecran-96*Menu_Facteur_X, Menu_Ordonnee_Texte,Menu_Facteur_X*96,Menu_Facteur_Y<<3,CM_Clair); Print_general(Largeur_ecran-Taille_nom*8*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,const 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 thin_font[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 x_pos; short y_pos; 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 (y_pos=0;y_pos<8;y_pos++) { for (x_pos=0;x_pos<6;x_pos++) { byte Couleur = (thin_font[Numero_car][y_pos] & (1 << (6-x_pos))) ? Couleur_texte:Couleur_fond; Pixel_dans_fenetre(x+(Indice*6+x_pos),y+y_pos,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==TOUCHE_ESC) Bouton_clicke=2; } while (Bouton_clicke<=0); Touche=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!=TOUCHE_ESC) && (Touche!=SDLK_o)); Touche=0; 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 x_pos; word y_pos; word Pos_menu_X; word Pos_menu_Y; byte Couleur; Pos_menu_Y=Bouton[Numero_bouton].Decalage_Y; Pos_menu_X=Bouton[Numero_bouton].Decalage_X; if (Bouton[Numero_bouton].Shape != FORME_BOUTON_TRIANGLE_BAS_DROITE) { Pos_menu_Y+=1; Pos_menu_X+=1; } for (y_pos=0;y_pos à 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*x_pos); word Largeur_ligne =Menu_Facteur_X<<4; // <=> à 16 pixels fct(Menu_Facteur) word Debut_Y =Fenetre_Pos_Y+(Menu_Facteur_Y*y_pos); 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=Coin_Y) || (Fin_X<=Fenetre_Pos_X) || (Debut_X>=Coin_X) ) Block(Debut_X,Debut_Y,width,height,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,width,Fin_Y-Coin_Y,Vraie_couleur); } else { if (Fin_Y>Coin_Y) Block(Debut_X,Coin_Y,width,Fin_Y-Coin_Y,Vraie_couleur); else Block(Coin_X,Debut_Y,Fin_X-Coin_X,height,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,width,Fin_Y-Coin_Y,Vraie_couleur); } else Block(Debut_X,Debut_Y,Fenetre_Pos_X-Debut_X,height,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,width,Fin_Y-Coin_Y,Vraie_couleur); } else { Block(Debut_X,Debut_Y,Fenetre_Pos_X-Debut_X,height,Vraie_couleur); Block(Coin_X,Debut_Y,Fin_X-Coin_X,height,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 x_pos; short y_pos; short relative_x; // besoin d'une variable signée short relative_y; // besoin d'une variable signée // Attention aux unités relative_x = ((short)Debut_X - (short)Fenetre_Pos_X); relative_y = ((short)Debut_Y - (short)Fenetre_Pos_Y); for (y_pos=relative_y;y_pos<(relative_y+height)&&y_pos=0&&y_pos>=0) Pixel_fond(x_pos,y_pos,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 start; short pos; short end; 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 x_pos, short y_pos, short width) { short Pos_X_reelle=Principal_X_Zoom+(x_pos-Loupe_Decalage_X)*Loupe_Facteur; short Pos_Y_reelle=(y_pos-Loupe_Decalage_Y)*Loupe_Facteur; short Largeur_reelle=width*Loupe_Facteur; short Pos_Y_Fin=(Pos_Y_reelle+Loupe_Facteur=Principal_X_Zoom) ) ) || (Fenetre) || (Forme_curseur==FORME_CURSEUR_SABLIER) ) shape=Forme_curseur; else shape=FORME_CURSEUR_FLECHE; switch(shape) { 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,13-Fin_X,13-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 (x_pos=Debut_X,Compteur_X=0;Compteur_X<15 && x_pos < Largeur_ecran;x_pos++,Compteur_X++) { if( x_pos < 0 ) continue; for (y_pos=Debut_Y,Compteur_Y=0;Compteur_Y<15 && y_pos < Hauteur_ecran;y_pos++,Compteur_Y++) { if( y_pos < 0 || y_pos >= Hauteur_ecran) continue; Couleur=SPRITE_CURSEUR[Temp][Compteur_Y][Compteur_X]; FOND_CURSEUR[Compteur_Y][Compteur_X]=Lit_pixel(x_pos,y_pos); if (Couleur!=CM_Trans) Pixel(x_pos,y_pos,Couleur); } } 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) && (x_pos=0) && (y_pos=Largeur_ecran) break; for (y_pos=Debut_Y,Compteur_Y=0;Compteur_Y<15;y_pos++,Compteur_Y++) { if(y_pos<0) continue; if(y_pos>=Hauteur_ecran) break; Couleur=SPRITE_CURSEUR[shape][Compteur_Y][Compteur_X]; // On sauvegarde dans FOND_CURSEUR pour restaurer plus tard FOND_CURSEUR[Compteur_Y][Compteur_X]=Lit_pixel(x_pos,y_pos); if (Couleur!=CM_Trans) Pixel(x_pos,y_pos,Couleur); } } UpdateRect(Max(Debut_X,0),Max(Debut_Y,0),Compteur_X,Compteur_Y); break; case FORME_CURSEUR_CIBLE_XOR : x_pos=Pinceau_X-Principal_Decalage_X; y_pos=Pinceau_Y-Principal_Decalage_Y; Compteur_X=(Loupe_Mode)?Principal_Split:Largeur_ecran; // width de la barre XOR if ((y_pos=Limite_Haut)) { Ligne_horizontale_XOR(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X); UpdateRect(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X,1); } if ((x_pos=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 { x_pos=Pinceau_X-Brosse_Centre_rotation_X; y_pos=Pinceau_Y-Brosse_Centre_rotation_Y; cosA=(float)x_pos/sqrt((x_pos*x_pos)+(y_pos*y_pos)); sinA=sin(acos(cosA)); if (y_pos>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 shape; 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 x_pos; int y_pos; 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) ) shape=Forme_curseur; else shape=FORME_CURSEUR_FLECHE; switch(shape) { 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,13-Fin_X,13-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 (y_pos=Debut_Y,Compteur_Y=0;Compteur_Y<15;y_pos++,Compteur_Y++) { if(y_pos>=Hauteur_ecran) break; for (x_pos=Debut_X,Compteur_X=0;Compteur_X<15;x_pos++,Compteur_X++) { if ( (x_pos<0) || (y_pos < 0)) continue; else if (x_pos>=Largeur_ecran) break; Pixel(x_pos,y_pos,FOND_CURSEUR[Compteur_Y][Compteur_X]); } } UpdateRect(Max(Debut_X,0),Max(Debut_Y,0),x_pos-Debut_X,y_pos-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) && (x_pos=0) && (y_pos=Largeur_ecran) break; for (y_pos=Debut_Y,Compteur_Y=0;Compteur_Y<15;y_pos++,Compteur_Y++) { if(y_pos<0) continue; if(y_pos>=Hauteur_ecran) break; Pixel(x_pos,y_pos,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 : x_pos=Pinceau_X-Principal_Decalage_X; y_pos=Pinceau_Y-Principal_Decalage_Y; Compteur_X=(Loupe_Mode)?Principal_Split:Largeur_ecran; // width de la barre XOR if ((y_pos=Limite_Haut)) { Ligne_horizontale_XOR(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X); UpdateRect(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X,1); } if ((x_pos=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 { x_pos=Pinceau_X-Brosse_Centre_rotation_X; y_pos=Pinceau_Y-Brosse_Centre_rotation_Y; cosA=(float)x_pos/sqrt((x_pos*x_pos)+(y_pos*y_pos)); sinA=sin(acos(cosA)); if (y_pos>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 width; word height; // ---/\/\/\ Partie non zoomée: /\/\/\--- if (Loupe_Mode) { if (Principal_Largeur_image