I'm not sure the way to get the program directory we use is ok for beos, but the official way of doing that is using C++ code. Maybe it's time to switch to some more unix way to store the config files... This should also fix watcom build (very untested as i'm using mingw to cross compile windows builds now) Also added begasus to the credits screen. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@325 416bcca6-2ee7-4201-b75f-2eb2f807beb1
		
			
				
	
	
		
			6244 lines
		
	
	
		
			202 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			6244 lines
		
	
	
		
			202 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*  Grafx2 - The Ultimate 256-color bitmap paint program
 | 
						|
 | 
						|
    Copyright 2008 Franck Charlet
 | 
						|
    Copyright 2007 Adrien Destugues
 | 
						|
    Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
 | 
						|
 | 
						|
    Grafx2 is free software; you can redistribute it and/or
 | 
						|
    modify it under the terms of the GNU General Public License
 | 
						|
    as published by the Free Software Foundation; version 2
 | 
						|
    of the License.
 | 
						|
 | 
						|
    Grafx2 is distributed in the hope that it will be useful,
 | 
						|
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
    GNU General Public License for more details.
 | 
						|
 | 
						|
    You should have received a copy of the GNU General Public License
 | 
						|
    along with Grafx2; if not, see <http://www.gnu.org/licenses/> or
 | 
						|
    write to the Free Software Foundation, Inc.,
 | 
						|
    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 | 
						|
*/
 | 
						|
#include "sdlscreen.h"
 | 
						|
#include "graph.h"
 | 
						|
#include "divers.h"
 | 
						|
#include <math.h>
 | 
						|
#ifdef __macosx__
 | 
						|
    #include <sys/malloc.h>
 | 
						|
#else
 | 
						|
    #include <malloc.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <string.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include "moteur.h"
 | 
						|
#include "boutons.h"
 | 
						|
#include "pages.h"
 | 
						|
#include "global.h"
 | 
						|
#include "struct.h"
 | 
						|
#include "erreurs.h"
 | 
						|
 | 
						|
#ifdef __linux__
 | 
						|
  #ifdef __macosx__
 | 
						|
    #include <sys/sysctl.h>
 | 
						|
  #else
 | 
						|
    #include <sys/sysinfo.h>
 | 
						|
  #endif
 | 
						|
#elif __WATCOMC__
 | 
						|
    #define _WIN32_WINNT 0x0500
 | 
						|
    #include <windows.h>
 | 
						|
#endif
 | 
						|
 | 
						|
// 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
 | 
						|
void Mettre_Ecran_A_Jour(short X, short Y, short Largeur, short Hauteur)
 | 
						|
{
 | 
						|
	short L_effectif, H_effectif;
 | 
						|
	short X_effectif;
 | 
						|
	short Y_effectif;
 | 
						|
 | 
						|
	// Première étape, si L ou H est négatif, on doit remettre la zone à l'endroit
 | 
						|
	if (Largeur < 0)
 | 
						|
	{
 | 
						|
		X += Largeur;
 | 
						|
		Largeur = - Largeur;
 | 
						|
	}
 | 
						|
 | 
						|
	if (Hauteur < 0)
 | 
						|
	{
 | 
						|
		Y += Hauteur;
 | 
						|
		Hauteur = - Hauteur;
 | 
						|
	}
 | 
						|
 | 
						|
	// D'abord on met à jour dans la zone écran normale
 | 
						|
	X_effectif = Max(X-Principal_Decalage_X,0);
 | 
						|
	Y_effectif = Max(Y-Principal_Decalage_Y,0);
 | 
						|
 | 
						|
	// Normalement il ne faudrait pas updater au delà du split quand on est en mode loupe,
 | 
						|
	// mais personne ne devrait demander d'update en dehors de cette limite, même le fill est contraint
 | 
						|
	// a rester dans la zone visible de l'image
 | 
						|
	if(X_effectif + Largeur <= Largeur_ecran) L_effectif = Largeur;
 | 
						|
	else L_effectif = Largeur_ecran - X_effectif;
 | 
						|
 | 
						|
	if(Y_effectif + Hauteur <= Menu_Ordonnee) H_effectif = Hauteur;
 | 
						|
	else H_effectif = Menu_Ordonnee - Y_effectif;
 | 
						|
 | 
						|
	UpdateRect(X_effectif,Y_effectif,L_effectif,H_effectif);
 | 
						|
 | 
						|
	// Et ensuite dans la partie zoomée
 | 
						|
	if(Loupe_Mode)
 | 
						|
	{
 | 
						|
		X_effectif = Min(Max((X-Loupe_Decalage_X)*Loupe_Facteur + 6 + Principal_Split + LARGEUR_BARRE_SPLIT,0), Largeur_ecran); // TODO: trouver d'ou sort le 6!
 | 
						|
		Y_effectif = Min(Max(Y-Loupe_Decalage_Y,0) * Loupe_Facteur, Menu_Ordonnee);
 | 
						|
 | 
						|
		Largeur *= Loupe_Facteur / 2; // ???!
 | 
						|
		Hauteur *= Loupe_Facteur;
 | 
						|
 | 
						|
		// Normalement il ne faudrait pas updater au delà du split quand on est en mode loupe,
 | 
						|
		// mais personne ne devrait demander d'update en dehors de cette limite, même le fill est contraint
 | 
						|
		// a rester dans la zone visible de l'image
 | 
						|
		if(X_effectif + (Largeur+2)*Menu_Facteur_X < Largeur_ecran) L_effectif = (Largeur+2) * Menu_Facteur_X;
 | 
						|
		else L_effectif = Largeur_ecran - X_effectif;
 | 
						|
 | 
						|
		if(Y_effectif + Hauteur <= Menu_Ordonnee) H_effectif = Hauteur;
 | 
						|
		else H_effectif = Menu_Ordonnee - Y_effectif;
 | 
						|
/* Très utile pour le debug :)
 | 
						|
		SDL_Rect r;
 | 
						|
		r.x=X_effectif;
 | 
						|
		r.y=Y_effectif;
 | 
						|
		r.h=r.w=3;
 | 
						|
		SDL_FillRect(Ecran_SDL,&r,3);
 | 
						|
*/
 | 
						|
		UpdateRect(X_effectif,Y_effectif,L_effectif,H_effectif);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
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<Best_dist)
 | 
						|
      {
 | 
						|
        Best_dist=Dist;
 | 
						|
        Best_color=Coul;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return Best_color;
 | 
						|
}
 | 
						|
 | 
						|
byte Meilleure_couleur_sans_exclusion(byte Rouge,byte Vert,byte Bleu)
 | 
						|
{
 | 
						|
  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++)
 | 
						|
  {
 | 
						|
    Delta_R=(int)Principal_Palette[Coul].R-Rouge;
 | 
						|
    Delta_V=(int)Principal_Palette[Coul].V-Vert;
 | 
						|
    Delta_B=(int)Principal_Palette[Coul].B-Bleu;
 | 
						|
 | 
						|
    if (!(Dist=(Delta_R*Delta_R*30)+(Delta_V*Delta_V*59)+(Delta_B*Delta_B*11)))
 | 
						|
      return Coul;
 | 
						|
 | 
						|
    if (Dist<Best_dist)
 | 
						|
    {
 | 
						|
      Best_dist=Dist;
 | 
						|
      Best_color=Coul;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return Best_color;
 | 
						|
}
 | 
						|
 | 
						|
void Calculer_les_4_meilleures_couleurs_pour_1_couleur_du_menu
 | 
						|
     (byte Rouge, byte Vert, byte Bleu, struct Composantes * Palette, byte * Table)
 | 
						|
{
 | 
						|
  short Coul;
 | 
						|
  int   Delta_R,Delta_V,Delta_B;
 | 
						|
  int   Dist;
 | 
						|
  int   Best_dist[4]={0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF};
 | 
						|
 | 
						|
 | 
						|
  for (Coul=0; Coul<256; Coul++)
 | 
						|
  {
 | 
						|
    Delta_R=(int)Palette[Coul].R-Rouge;
 | 
						|
    Delta_V=(int)Palette[Coul].V-Vert;
 | 
						|
    Delta_B=(int)Palette[Coul].B-Bleu;
 | 
						|
 | 
						|
    Dist=(Delta_R*Delta_R*30)+(Delta_V*Delta_V*59)+(Delta_B*Delta_B*11);
 | 
						|
 | 
						|
    if (Dist<Best_dist[0])
 | 
						|
    {
 | 
						|
      Best_dist[3]=Best_dist[2];
 | 
						|
      Best_dist[2]=Best_dist[1];
 | 
						|
      Best_dist[1]=Best_dist[0];
 | 
						|
      Best_dist[0]=Dist;
 | 
						|
      Table[3]=Table[2];
 | 
						|
      Table[2]=Table[1];
 | 
						|
      Table[1]=Table[0];
 | 
						|
      Table[0]=Coul;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      if (Dist<Best_dist[1])
 | 
						|
      {
 | 
						|
        Best_dist[3]=Best_dist[2];
 | 
						|
        Best_dist[2]=Best_dist[1];
 | 
						|
        Best_dist[1]=Dist;
 | 
						|
        Table[3]=Table[2];
 | 
						|
        Table[2]=Table[1];
 | 
						|
        Table[1]=Coul;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if (Dist<Best_dist[2])
 | 
						|
        {
 | 
						|
          Best_dist[3]=Best_dist[2];
 | 
						|
          Best_dist[2]=Dist;
 | 
						|
          Table[3]=Table[2];
 | 
						|
          Table[2]=Coul;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        if (Dist<Best_dist[3])
 | 
						|
        {
 | 
						|
          Best_dist[3]=Dist;
 | 
						|
          Table[3]=Coul;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
byte Old_Noir;
 | 
						|
byte Old_Fonce;
 | 
						|
byte Old_Clair;
 | 
						|
byte Old_Blanc;
 | 
						|
byte Old_Trans;
 | 
						|
 | 
						|
void Remap_pixel(byte * Pix)
 | 
						|
{
 | 
						|
  if (*Pix==Old_Clair)         // On commence par tester le Gris clair
 | 
						|
    *Pix=CM_Clair;             // qui est pas mal utilisé.
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (*Pix==Old_Noir)        // Puis le Noir...
 | 
						|
      *Pix=CM_Noir;
 | 
						|
    else
 | 
						|
    {
 | 
						|
      if (*Pix==Old_Fonce)     // etc...
 | 
						|
        *Pix=CM_Fonce;
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if (*Pix==Old_Blanc)
 | 
						|
          *Pix=CM_Blanc;
 | 
						|
        else
 | 
						|
        {
 | 
						|
          if (*Pix==Old_Trans)
 | 
						|
            *Pix=CM_Trans;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void Afficher_palette_du_menu_en_evitant_la_fenetre(byte * Table)
 | 
						|
{
 | 
						|
  // On part du principe qu'il n'y a que le bas d'une fenêtre qui puisse
 | 
						|
  // empiéter sur la palette... Et c'est déjà pas mal!
 | 
						|
  byte Couleur,Vraie_couleur;
 | 
						|
  word Debut_X,Debut_Y;
 | 
						|
  word Fin_X,Fin_Y;
 | 
						|
  word Largeur;
 | 
						|
  word Hauteur;
 | 
						|
  word Coin_X=Fenetre_Pos_X+Fenetre_Largeur; // |_ Coin bas-droit
 | 
						|
  word Coin_Y=Fenetre_Pos_Y+Fenetre_Hauteur; // |  de la fenêtre +1
 | 
						|
 | 
						|
 | 
						|
  if (Config.Couleurs_separees)
 | 
						|
  {
 | 
						|
    Largeur=(Menu_Taille_couleur-1)*Menu_Facteur_X;
 | 
						|
    Hauteur=Menu_Facteur_Y*3;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    Largeur=Menu_Taille_couleur*Menu_Facteur_X;
 | 
						|
    Hauteur=Menu_Facteur_Y<<2;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Couleur=0,Vraie_couleur=Couleur_debut_palette;Couleur<64;Couleur++,Vraie_couleur++)
 | 
						|
  {
 | 
						|
    if (Table[Vraie_couleur]!=Vraie_couleur)
 | 
						|
    {
 | 
						|
      Debut_X=(LARGEUR_MENU+1+(Couleur>>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_X<Coin_X)
 | 
						|
          {
 | 
						|
            if (Fin_Y>Coin_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);
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  UpdateRect((LARGEUR_MENU+1)*Menu_Facteur_X,Menu_Ordonnee,Largeur,Hauteur);
 | 
						|
//    UpdateRect(LARGEUR_MENU*Menu_Facteur_X,Menu_Ordonnee,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<Menu_Ordonnee_avant_fenetre)?Temp:Menu_Ordonnee_avant_fenetre-Fenetre_Pos_Y,
 | 
						|
                 Table_de_conversion);
 | 
						|
 | 
						|
    if (Menu_visible_avant_fenetre)
 | 
						|
    {
 | 
						|
      Remap_screen(0, Menu_Ordonnee_avant_fenetre,
 | 
						|
                   Largeur_ecran, Hauteur_ecran-Menu_Ordonnee_avant_fenetre,
 | 
						|
                   Table_de_conversion);
 | 
						|
      // On passe la table juste pour ne rafficher que les couleurs modifiées
 | 
						|
      Afficher_palette_du_menu_en_evitant_la_fenetre(Table_de_conversion);
 | 
						|
    }
 | 
						|
    /*
 | 
						|
       Il faudrait peut-être remapper les pointillés délimitant l'image.
 | 
						|
       Mais ça va être chiant parce qu'ils peuvent être affichés en mode Loupe.
 | 
						|
       Mais de toutes façons, c'est franchement facultatif...
 | 
						|
    */
 | 
						|
    // Remappage de la partie du fond de la fenetre qui cacherait le menu...
 | 
						|
    if (Menu_visible_avant_fenetre)
 | 
						|
      Remappe_fond_fenetres(Table_de_conversion, Menu_Ordonnee_avant_fenetre, Hauteur_ecran);
 | 
						|
  }
 | 
						|
  
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void Calculer_couleurs_menu_optimales(struct Composantes * Palette)
 | 
						|
{
 | 
						|
  byte Table[4];
 | 
						|
  short I,J,K;
 | 
						|
 | 
						|
 | 
						|
  Old_Noir =CM_Noir;
 | 
						|
  Old_Fonce=CM_Fonce;
 | 
						|
  Old_Clair=CM_Clair;
 | 
						|
  Old_Blanc=CM_Blanc;
 | 
						|
  Old_Trans=CM_Trans;
 | 
						|
 | 
						|
  // Recherche du noir
 | 
						|
  Calculer_les_4_meilleures_couleurs_pour_1_couleur_du_menu
 | 
						|
    (Coul_menu_pref[0].R, Coul_menu_pref[0].V, Coul_menu_pref[0].B,Palette,Table);
 | 
						|
  CM_Noir=Table[0];
 | 
						|
 | 
						|
  // Recherche du blanc
 | 
						|
  Calculer_les_4_meilleures_couleurs_pour_1_couleur_du_menu
 | 
						|
    (Coul_menu_pref[3].R, Coul_menu_pref[3].V, Coul_menu_pref[3].B,Palette,Table);
 | 
						|
  if (CM_Noir!=Table[0])
 | 
						|
    CM_Blanc=Table[0];
 | 
						|
  else
 | 
						|
    CM_Blanc=Table[1];
 | 
						|
 | 
						|
  // Recherche du gris clair
 | 
						|
  Calculer_les_4_meilleures_couleurs_pour_1_couleur_du_menu
 | 
						|
    (Coul_menu_pref[2].R, Coul_menu_pref[2].V, Coul_menu_pref[2].B,Palette,Table);
 | 
						|
  if ( (CM_Noir!=Table[0]) && (CM_Blanc!=Table[0]) )
 | 
						|
    CM_Clair=Table[0];
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if ( (CM_Noir!=Table[1]) && (CM_Blanc!=Table[1]) )
 | 
						|
      CM_Clair=Table[1];
 | 
						|
    else
 | 
						|
      CM_Clair=Table[2];
 | 
						|
  }
 | 
						|
 | 
						|
  // Recherche du gris foncé
 | 
						|
  Calculer_les_4_meilleures_couleurs_pour_1_couleur_du_menu
 | 
						|
    (Coul_menu_pref[1].R, Coul_menu_pref[1].V, Coul_menu_pref[1].B,Palette,Table);
 | 
						|
  if ( (CM_Noir!=Table[0]) && (CM_Blanc!=Table[0]) && (CM_Clair!=Table[0]) )
 | 
						|
    CM_Fonce=Table[0];
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if ( (CM_Noir!=Table[1]) && (CM_Blanc!=Table[1]) && (CM_Clair!=Table[1]) )
 | 
						|
      CM_Fonce=Table[1];
 | 
						|
    else
 | 
						|
    {
 | 
						|
      if ( (CM_Noir!=Table[2]) && (CM_Blanc!=Table[2]) && (CM_Clair!=Table[2]) )
 | 
						|
        CM_Fonce=Table[2];
 | 
						|
      else
 | 
						|
        CM_Fonce=Table[3];
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // C'est peu probable mais il est possible que CM_Clair soit plus foncée que
 | 
						|
  // CM_Fonce. Dans ce cas, on les inverse.
 | 
						|
  if ( ((Palette[CM_Clair].R*30)+(Palette[CM_Clair].V*59)+(Palette[CM_Clair].B*11)) <
 | 
						|
       ((Palette[CM_Fonce].R*30)+(Palette[CM_Fonce].V*59)+(Palette[CM_Fonce].B*11)) )
 | 
						|
  {
 | 
						|
    I=CM_Clair;
 | 
						|
    CM_Clair=CM_Fonce;
 | 
						|
    CM_Fonce=I;
 | 
						|
  }
 | 
						|
 | 
						|
  // On cherche une couleur de transparence différente des 4 autres.
 | 
						|
  for (CM_Trans=0; ((CM_Trans==CM_Noir) || (CM_Trans==CM_Fonce) ||
 | 
						|
                   (CM_Trans==CM_Clair) || (CM_Trans==CM_Blanc)); CM_Trans++);
 | 
						|
 | 
						|
  // Et maintenant, on "remappe" tous les sprites, etc...
 | 
						|
  if ( (CM_Clair!=Old_Clair)
 | 
						|
    || (CM_Fonce!=Old_Fonce)
 | 
						|
    || (CM_Blanc!=Old_Blanc)
 | 
						|
    || (CM_Noir !=Old_Noir )
 | 
						|
    || (CM_Trans!=Old_Trans) )
 | 
						|
  {
 | 
						|
      // Sprites du curseur
 | 
						|
    for (K=0; K<NB_SPRITES_CURSEUR; K++)
 | 
						|
      for (J=0; J<HAUTEUR_SPRITE_CURSEUR; J++)
 | 
						|
        for (I=0; I<LARGEUR_SPRITE_CURSEUR; I++)
 | 
						|
          Remap_pixel(&SPRITE_CURSEUR[K][J][I]);
 | 
						|
      // Le menu
 | 
						|
    for (J=0; J<HAUTEUR_MENU; J++)
 | 
						|
      for (I=0; I<LARGEUR_MENU; I++)
 | 
						|
        Remap_pixel(&BLOCK_MENU[J][I]);
 | 
						|
      // Sprites du menu
 | 
						|
    for (K=0; K<NB_SPRITES_MENU; K++)
 | 
						|
      for (J=0; J<HAUTEUR_SPRITE_MENU; J++)
 | 
						|
        for (I=0; I<LARGEUR_SPRITE_MENU; I++)
 | 
						|
          Remap_pixel(&SPRITE_MENU[K][J][I]);
 | 
						|
      // Sprites d'effets
 | 
						|
    for (K=0; K<NB_SPRITES_EFFETS; K++)
 | 
						|
      for (J=0; J<HAUTEUR_SPRITE_MENU; J++)
 | 
						|
        for (I=0; I<LARGEUR_SPRITE_MENU; I++)
 | 
						|
          Remap_pixel(&SPRITE_EFFET[K][J][I]);
 | 
						|
      // Fonte de l'aide
 | 
						|
    for (K=0; K<315; K++)
 | 
						|
      for (J=0; J<8; J++)
 | 
						|
        for (I=0; I<6; I++)
 | 
						|
          Remap_pixel(&Fonte_help[K][I][J]);
 | 
						|
      // Sprites de lecteurs (drives)
 | 
						|
    for (K=0; K<NB_SPRITES_DRIVES; K++)
 | 
						|
      for (J=0; J<HAUTEUR_SPRITE_DRIVE; J++)
 | 
						|
        for (I=0; I<LARGEUR_SPRITE_DRIVE; I++)
 | 
						|
          Remap_pixel(&SPRITE_DRIVE[K][J][I]);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// 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();
 | 
						|
  */
 | 
						|
    #ifdef __linux__
 | 
						|
      #ifdef __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;
 | 
						|
      #else
 | 
						|
        struct sysinfo info;
 | 
						|
        sysinfo(&info);
 | 
						|
        return info.freeram*info.mem_unit;
 | 
						|
      #endif
 | 
						|
    #elif __WATCOMC__
 | 
						|
         MEMORYSTATUSEX mstt;
 | 
						|
         mstt.dwLength = sizeof(MEMORYSTATUSEX);
 | 
						|
         GlobalMemoryStatusEx(&mstt);
 | 
						|
         return mstt.ullAvailPhys;
 | 
						|
    #else
 | 
						|
        return 10*1024*1024;
 | 
						|
    #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 (A<B)?A:B;
 | 
						|
}
 | 
						|
 | 
						|
// Retourne le maximum entre deux nombres
 | 
						|
int Max(int A,int B)
 | 
						|
{
 | 
						|
  return (A>B)?A:B;
 | 
						|
}
 | 
						|
 | 
						|
void Transformer_point(short X, short Y, float cosA, float sinA,
 | 
						|
                       short * Xr, short * Yr)
 | 
						|
{
 | 
						|
  *Xr=Round(((float)X*cosA)+((float)Y*sinA));
 | 
						|
  *Yr=Round(((float)Y*cosA)-((float)X*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_image<Principal_Decalage_X+Principal_Split)
 | 
						|
      Principal_Decalage_X=Principal_Largeur_image-Principal_Split;
 | 
						|
  }
 | 
						|
  else
 | 
						|
    Principal_Decalage_X=0;
 | 
						|
 | 
						|
  // Centrage en Y
 | 
						|
  if (Principal_Hauteur_image>Menu_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<Principal_Decalage_Y+Menu_Ordonnee)
 | 
						|
      Principal_Decalage_Y=Principal_Hauteur_image-Menu_Ordonnee;
 | 
						|
  }
 | 
						|
  else
 | 
						|
    Principal_Decalage_Y=0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// - Calcul des données du split en fonction de la proportion de chaque zone -
 | 
						|
void Calculer_split(void)
 | 
						|
{
 | 
						|
  //short Temp;
 | 
						|
  short X_theorique=Round(Principal_Proportion_split*Largeur_ecran);
 | 
						|
 | 
						|
  Principal_X_Zoom=Largeur_ecran-(((Largeur_ecran+(Loupe_Facteur>>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)<Largeur_ecran-(Menu_Facteur_X*LARGEUR_BARRE_SPLIT))
 | 
						|
  {
 | 
						|
    Principal_Split+=Loupe_Facteur;
 | 
						|
    Principal_X_Zoom+=Loupe_Facteur;
 | 
						|
  }
 | 
						|
  // Correction en cas de débordement sur la droite
 | 
						|
  X_theorique=Largeur_ecran-((NB_PIXELS_ZOOMES_MIN-1)*Loupe_Facteur);
 | 
						|
  while (Principal_X_Zoom>=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<Loupe_Decalage_X+Loupe_Largeur)
 | 
						|
      Loupe_Decalage_X=Principal_Largeur_image-Loupe_Largeur;
 | 
						|
    if (Loupe_Decalage_X<0) Loupe_Decalage_X=0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// -------- 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;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// ------------ 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_image<Menu_Ordonnee;
 | 
						|
 | 
						|
 | 
						|
  // On vérifie que la limite à droite est visible:
 | 
						|
  if (Droite_visible)
 | 
						|
  {
 | 
						|
    Debut=Limite_Haut;
 | 
						|
    Fin=(Limite_Bas<Principal_Hauteur_image)?
 | 
						|
        Limite_Bas:Principal_Hauteur_image;
 | 
						|
 | 
						|
    if (Bas_visible)
 | 
						|
      Fin++;
 | 
						|
 | 
						|
    // Juste le temps d'afficher les limites, on étend les limites de la loupe
 | 
						|
    // aux limites visibles, car sinon Pixel_Preview ne voudra pas afficher.
 | 
						|
    Ancienne_Limite_Zoom=Limite_Droite_Zoom;
 | 
						|
    Limite_Droite_Zoom=Limite_visible_Droite_Zoom;
 | 
						|
 | 
						|
    for (Pos=Debut;Pos<=Fin;Pos++)
 | 
						|
      Pixel_Preview(Principal_Largeur_image,Pos,((Pos+Principal_Hauteur_image)&1)?CM_Blanc:CM_Noir);
 | 
						|
 | 
						|
    UpdateRect(Principal_Largeur_image,Debut,1,Fin-Debut + 1);
 | 
						|
    // On restaure la bonne valeur des limites
 | 
						|
    Limite_Droite_Zoom=Ancienne_Limite_Zoom;
 | 
						|
  }
 | 
						|
 | 
						|
  // On vérifie que la limite en bas est visible:
 | 
						|
  if (Bas_visible)
 | 
						|
  {
 | 
						|
    Debut=Limite_Gauche;
 | 
						|
    Fin=(Limite_Droite<Principal_Largeur_image)?
 | 
						|
        Limite_Droite:Principal_Largeur_image;
 | 
						|
 | 
						|
    // On étend également les limites en bas (comme pour la limite droit)
 | 
						|
    Ancienne_Limite_Zoom=Limite_Bas_Zoom;
 | 
						|
    Limite_Bas_Zoom=Limite_visible_Bas_Zoom;
 | 
						|
 | 
						|
    for (Pos=Debut;Pos<=Fin;Pos++)
 | 
						|
      Pixel_Preview(Pos,Principal_Hauteur_image,((Pos+Principal_Hauteur_image)&1)?CM_Blanc:CM_Noir);
 | 
						|
 | 
						|
    UpdateRect(Debut,Principal_Hauteur_image,Fin-Debut + 1,1);
 | 
						|
 | 
						|
    // On restaure la bonne valeur des limites
 | 
						|
    Limite_Bas_Zoom=Ancienne_Limite_Zoom;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// 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<Nb_modes_video; Indice_mode++)
 | 
						|
    // Attention les vieilles fonctions de lecture .ini mettent tout en MAJUSCULE.
 | 
						|
    if (!strcasecmp(Libelle_mode(Indice_mode), Argument))
 | 
						|
      return Indice_mode;
 | 
						|
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//--------------------- Initialisation d'un mode vidéo -----------------------
 | 
						|
 | 
						|
void Initialiser_mode_video(int Largeur, int Hauteur, int Fullscreen)
 | 
						|
{
 | 
						|
  int Sensibilite_X;
 | 
						|
  int Sensibilite_Y;
 | 
						|
  int Indice;
 | 
						|
  int Facteur;
 | 
						|
  
 | 
						|
  if (Largeur_ecran!=Largeur ||
 | 
						|
      Hauteur_ecran!=Hauteur ||
 | 
						|
      Mode_video[Resolution_actuelle].Fullscreen != Fullscreen)
 | 
						|
  {
 | 
						|
    // Valeurs raisonnables: minimum 320x200
 | 
						|
    if (Largeur < 320)
 | 
						|
      Largeur = 320;
 | 
						|
    if (Hauteur < 200)
 | 
						|
      Hauteur = 200;
 | 
						|
    // La largeur doit être un multiple de 4
 | 
						|
    Largeur = (Largeur + 3 ) & 0xFFFFFFFC;
 | 
						|
 | 
						|
    // Taille des menus
 | 
						|
    if (Largeur/320 > Hauteur/200)
 | 
						|
      Facteur=Hauteur/200;
 | 
						|
    else
 | 
						|
      Facteur=Largeur/320;
 | 
						|
  
 | 
						|
    Largeur_ecran = Largeur;
 | 
						|
    Hauteur_ecran = Hauteur;
 | 
						|
    Plein_ecran   = Fullscreen;
 | 
						|
 | 
						|
    switch (Config.Ratio)
 | 
						|
    {
 | 
						|
      case 1: // adapter tout
 | 
						|
        Menu_Facteur_X=Facteur;
 | 
						|
        Menu_Facteur_Y=Facteur;
 | 
						|
        break;
 | 
						|
      case 2: // adapter légèrement
 | 
						|
        Menu_Facteur_X=Facteur-1;
 | 
						|
        if (Menu_Facteur_X<1) Menu_Facteur_X=1;
 | 
						|
        Menu_Facteur_Y=Facteur-1;
 | 
						|
        if (Menu_Facteur_Y<1) Menu_Facteur_Y=1;
 | 
						|
        break;
 | 
						|
      default: // ne pas adapter
 | 
						|
        Menu_Facteur_X=1;
 | 
						|
        Menu_Facteur_Y=1;
 | 
						|
    }
 | 
						|
 | 
						|
    if (Buffer_de_ligne_horizontale)
 | 
						|
      free(Buffer_de_ligne_horizontale);
 | 
						|
 | 
						|
    Buffer_de_ligne_horizontale=(byte *)malloc((Largeur_ecran>Principal_Largeur_image)?Largeur_ecran:Principal_Largeur_image);
 | 
						|
 | 
						|
    switch (MODE_SDL)
 | 
						|
    {
 | 
						|
        case MODE_SDL:
 | 
						|
            Pixel = Pixel_SDL;
 | 
						|
            Lit_pixel= Lit_Pixel_SDL;
 | 
						|
            Display_screen = Afficher_partie_de_l_ecran_SDL;
 | 
						|
            Block = Block_SDL;
 | 
						|
            Pixel_Preview_Normal = Pixel_Preview_Normal_SDL;
 | 
						|
            Pixel_Preview_Loupe = Pixel_Preview_Loupe_SDL;
 | 
						|
            Ligne_horizontale_XOR = Ligne_horizontale_XOR_SDL;
 | 
						|
            Ligne_verticale_XOR = Ligne_verticale_XOR_SDL;
 | 
						|
            Display_brush_Color = Display_brush_Color_SDL;
 | 
						|
            Display_brush_Mono = Display_brush_Mono_SDL;
 | 
						|
            Clear_brush = Clear_brush_SDL;
 | 
						|
            Remap_screen = Remap_screen_SDL;
 | 
						|
            Afficher_ligne = Afficher_une_ligne_ecran_SDL;
 | 
						|
            Lire_ligne = Lire_une_ligne_ecran_SDL;
 | 
						|
            Display_zoomed_screen = Afficher_partie_de_l_ecran_zoomee_SDL;
 | 
						|
            Display_brush_Color_zoom = Display_brush_Color_zoom_SDL;
 | 
						|
            Display_brush_Mono_zoom = Display_brush_Mono_zoom_SDL;
 | 
						|
            Clear_brush_zoom = Clear_brush_zoom_SDL;
 | 
						|
            Set_Mode_SDL();
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    
 | 
						|
    Set_palette(Principal_Palette);
 | 
						|
 | 
						|
    if (!Fullscreen)
 | 
						|
      Resolution_actuelle=0;
 | 
						|
    else
 | 
						|
      for (Indice=1; Indice<Nb_modes_video; Indice++)
 | 
						|
      {
 | 
						|
        if (Mode_video[Indice].Largeur==Largeur_ecran &&
 | 
						|
            Mode_video[Indice].Hauteur==Hauteur_ecran)
 | 
						|
        {
 | 
						|
          Resolution_actuelle=Indice;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
    Menu_Taille_couleur = ((Largeur_ecran/Menu_Facteur_X)-(LARGEUR_MENU+2)) >> 3;
 | 
						|
    Menu_Ordonnee = Hauteur_ecran;
 | 
						|
    if (Menu_visible)
 | 
						|
      Menu_Ordonnee -= HAUTEUR_MENU * Menu_Facteur_Y;
 | 
						|
    Menu_Ordonnee_Texte = Hauteur_ecran-(Menu_Facteur_Y<<3);
 | 
						|
    Bouton[BOUTON_CHOIX_COL].Largeur=(Menu_Taille_couleur<<3)-1;
 | 
						|
 | 
						|
    Sensibilite_X = Config.Indice_Sensibilite_souris_X;
 | 
						|
    Sensibilite_Y = Config.Indice_Sensibilite_souris_Y;
 | 
						|
    Sensibilite_X>>=Mouse_Facteur_de_correction_X;
 | 
						|
    Sensibilite_Y>>=Mouse_Facteur_de_correction_Y;
 | 
						|
    Sensibilite_souris(Sensibilite_X?Sensibilite_X:1,Sensibilite_Y?Sensibilite_Y:1);
 | 
						|
 | 
						|
    Brouillon_Decalage_X=0; // |  Il faut penser à éviter les incohérences
 | 
						|
    Brouillon_Decalage_Y=0; // |- de décalage du brouillon par rapport à
 | 
						|
    Brouillon_Loupe_Mode=0; // |  la résolution.
 | 
						|
  }
 | 
						|
 | 
						|
  Pixel_Preview=Pixel_Preview_Normal;
 | 
						|
 | 
						|
  Principal_Decalage_X=0; // Il faut quand même modifier ces valeurs à chaque
 | 
						|
  Principal_Decalage_Y=0; // fois car on n'est pas à l'abri d'une modification
 | 
						|
                          // des dimensions de l'image.
 | 
						|
  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[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<Couleur_debut_palette+64) && (Menu_visible))
 | 
						|
  {
 | 
						|
    if (Config.Couleurs_separees)
 | 
						|
    {
 | 
						|
      Debut_X=(LARGEUR_MENU+((Fore_color-Couleur_debut_palette)>>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<Fin_Y; Indice++)
 | 
						|
          Block(Debut_X*Menu_Facteur_X,Menu_Ordonnee+(Indice*Menu_Facteur_Y),
 | 
						|
                Menu_Facteur_X,Menu_Facteur_Y,
 | 
						|
                ((Indice+Debut_X)&1)?CM_Blanc:CM_Noir);
 | 
						|
 | 
						|
        for (Indice=Debut_Y+1; Indice<Fin_Y; Indice++)
 | 
						|
          Block(Fin_X*Menu_Facteur_X,Menu_Ordonnee+(Indice*Menu_Facteur_Y),
 | 
						|
                Menu_Facteur_X,Menu_Facteur_Y,
 | 
						|
                ((Indice+Fin_X)&1)?CM_Blanc:CM_Noir);
 | 
						|
 | 
						|
        for (Indice=Debut_X; Indice<=Fin_X; Indice++)
 | 
						|
          Block(Indice*Menu_Facteur_X,Menu_Ordonnee+(Fin_Y*Menu_Facteur_Y),
 | 
						|
                Menu_Facteur_X,Menu_Facteur_Y,
 | 
						|
                ((Indice+Fin_Y)&1)?CM_Blanc:CM_Noir);
 | 
						|
 | 
						|
        UpdateRect(Debut_X*Menu_Facteur_X,Debut_Y*Menu_Facteur_X,Menu_Taille_couleur*Menu_Facteur_X,Menu_Ordonnee+Menu_Facteur_Y*4);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
  // -- Afficher la palette dans le menu --
 | 
						|
 | 
						|
void Afficher_palette_du_menu(void)
 | 
						|
{
 | 
						|
  byte Couleur;
 | 
						|
 | 
						|
  if (Menu_visible)
 | 
						|
  {
 | 
						|
    Block(LARGEUR_MENU*Menu_Facteur_X,Menu_Ordonnee,Largeur_ecran-(LARGEUR_MENU*Menu_Facteur_X),(HAUTEUR_MENU-9)*Menu_Facteur_Y,CM_Noir);
 | 
						|
 | 
						|
    if (Config.Couleurs_separees)
 | 
						|
      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-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)
 | 
						|
  {
 | 
						|
    while (Fore_color<Couleur_debut_palette)
 | 
						|
      Couleur_debut_palette-=8;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    while (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<HAUTEUR_MENU;Pos_Y++)
 | 
						|
      for (Pos_X=0;Pos_X<LARGEUR_MENU;Pos_X++)
 | 
						|
        Pixel_dans_menu(Pos_X,Pos_Y,BLOCK_MENU[Pos_Y][Pos_X]);
 | 
						|
    // Affichage de la bande grise sous la palette
 | 
						|
    Block(LARGEUR_MENU*Menu_Facteur_X,Menu_Ordonnee_Texte-Menu_Facteur_Y,Largeur_ecran-(LARGEUR_MENU*Menu_Facteur_X),9*Menu_Facteur_Y,CM_Clair);
 | 
						|
 | 
						|
    // Affichage de la palette
 | 
						|
    Afficher_palette_du_menu();
 | 
						|
 | 
						|
    // Affichage des couleurs de travail
 | 
						|
    Afficher_foreback();
 | 
						|
 | 
						|
    if (!Fenetre)
 | 
						|
    {
 | 
						|
      if ((Mouse_Y<Menu_Ordonnee) &&
 | 
						|
          ( (!Loupe_Mode) || (Mouse_X<Principal_Split) || (Mouse_X>=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
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Table de conversion ANSI->OEM
 | 
						|
// Les deux fontes générales sont en encodage OEM
 | 
						|
unsigned char Caractere_OEM[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 
 | 
						|
 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 
 | 
						|
 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 
 | 
						|
 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 
 | 
						|
 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 
 | 
						|
 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 
 | 
						|
 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 
 | 
						|
 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 
 | 
						|
 63, 63, 39, 159, 34, 46, 197, 206, 94, 37, 83, 60, 79, 63, 90, 63, 
 | 
						|
 63, 39, 39, 34, 34, 7, 45, 45, 126, 84, 115, 62, 111, 63, 122, 89, 
 | 
						|
 255, 173, 189, 156, 207, 190, 221, 245, 249, 184, 166, 174, 170, 240, 169, 238, 
 | 
						|
 248, 241, 253, 252, 239, 230, 244, 250, 247, 251, 167, 175, 172, 171, 243, 168, 
 | 
						|
 183, 181, 182, 199, 142, 143, 146, 128, 212, 144, 210, 211, 222, 214, 215, 216, 
 | 
						|
 209, 165, 227, 224, 226, 229, 153, 158, 157, 235, 233, 234, 154, 237, 232, 225, 
 | 
						|
 133, 160, 131, 198, 132, 134, 145, 135, 138, 130, 136, 137, 141, 161, 140, 139, 
 | 
						|
 208, 164, 149, 162, 147, 228, 148, 246, 155, 151, 163, 150, 129, 236, 231}; 
 | 
						|
 | 
						|
// -- 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;
 | 
						|
  short Pos_X;
 | 
						|
  short Pos_Y;
 | 
						|
  unsigned char Caractere;
 | 
						|
  short Reel_X;
 | 
						|
  short Reel_Y;
 | 
						|
  short Largeur;
 | 
						|
  short Repeat_Menu_Facteur_X;
 | 
						|
  short Repeat_Menu_Facteur_Y;
 | 
						|
 | 
						|
  Reel_Y=Y;
 | 
						|
  Largeur=strlen(Chaine)*Menu_Facteur_X*8;
 | 
						|
  for (Pos_Y=0;Pos_Y<8;Pos_Y++)
 | 
						|
  {
 | 
						|
    Reel_X=0; // Position dans le buffer
 | 
						|
    for (Indice=0;Chaine[Indice]!='\0';Indice++)
 | 
						|
    {
 | 
						|
      Caractere=Chaine[Indice];
 | 
						|
      for (Pos_X=0;Pos_X<8;Pos_X++)
 | 
						|
        for (Repeat_Menu_Facteur_X=0;Repeat_Menu_Facteur_X<Menu_Facteur_X;Repeat_Menu_Facteur_X++)
 | 
						|
          Buffer_de_ligne_horizontale[Reel_X++]=(*(Fonte+(*(Caractere_OEM+Caractere)<<6)+(Pos_X<<3)+Pos_Y)?Couleur_texte:Couleur_fond);
 | 
						|
    }
 | 
						|
    for (Repeat_Menu_Facteur_Y=0;Repeat_Menu_Facteur_Y<Menu_Facteur_Y;Repeat_Menu_Facteur_Y++)
 | 
						|
      Afficher_ligne(X,Reel_Y++,Largeur,Buffer_de_ligne_horizontale);
 | 
						|
  }
 | 
						|
  UpdateRect(X,Y,Largeur,8*Menu_Facteur_Y); // TODO: pas utile dans Print_Dans_Fenetre, donc voir ou on en a vraiment besoin...
 | 
						|
}
 | 
						|
 | 
						|
  // -- Afficher un caractère dans une fenêtre --
 | 
						|
 | 
						|
void Print_char_dans_fenetre(short Pos_X,short Pos_Y,unsigned char Caractere,byte Couleur_texte,byte Couleur_fond)
 | 
						|
{
 | 
						|
  short X,Y;
 | 
						|
  Pos_X=(Pos_X*Menu_Facteur_X)+Fenetre_Pos_X;
 | 
						|
  Pos_Y=(Pos_Y*Menu_Facteur_Y)+Fenetre_Pos_Y;
 | 
						|
 | 
						|
  for (X=0;X<8;X++)
 | 
						|
    for (Y=0;Y<8;Y++)
 | 
						|
      Block(Pos_X+(X*Menu_Facteur_X), Pos_Y+(Y*Menu_Facteur_Y),
 | 
						|
            Menu_Facteur_X, Menu_Facteur_Y,
 | 
						|
            (*(Fonte+(*(Caractere_OEM+Caractere)<<6)+(X<<3)+Y)?Couleur_texte:Couleur_fond));
 | 
						|
}
 | 
						|
 | 
						|
  // -- Afficher un caractère sans fond dans une fenêtre --
 | 
						|
 | 
						|
void Print_char_transparent_dans_fenetre(short Pos_X,short Pos_Y,unsigned char Caractere,byte Couleur)
 | 
						|
{
 | 
						|
  short X,Y;
 | 
						|
 | 
						|
  Pos_X=(Pos_X*Menu_Facteur_X)+Fenetre_Pos_X;
 | 
						|
  Pos_Y=(Pos_Y*Menu_Facteur_Y)+Fenetre_Pos_Y;
 | 
						|
 | 
						|
  for (X=0;X<8;X++)
 | 
						|
    for (Y=0;Y<8;Y++)
 | 
						|
    {
 | 
						|
      if (*(Fonte+(*(Caractere_OEM+Caractere)<<6)+(X<<3)+Y))
 | 
						|
        Block(Pos_X+(X*Menu_Facteur_X), Pos_Y+(Y*Menu_Facteur_Y),
 | 
						|
              Menu_Facteur_X, Menu_Facteur_Y, Couleur);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
  // -- Afficher une chaîne dans une fenêtre, avec taille maxi --
 | 
						|
 | 
						|
void Print_dans_fenetre_limite(short X,short Y,char * Chaine,byte Taille,byte Couleur_texte,byte Couleur_fond)
 | 
						|
{
 | 
						|
  char Chaine_affichee[256];
 | 
						|
  strncpy(Chaine_affichee, Chaine, Taille);
 | 
						|
  Chaine_affichee[255]='\0';
 | 
						|
  
 | 
						|
  if (strlen(Chaine_affichee) > Taille)
 | 
						|
  {
 | 
						|
    Chaine_affichee[Taille-1]=CARACTERE_TRIANGLE_DROIT;
 | 
						|
    Chaine_affichee[Taille]='\0';
 | 
						|
  }
 | 
						|
  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);
 | 
						|
}
 | 
						|
 | 
						|
  // -- 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);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Afficher les coordonnées du pinceau dans le menu --
 | 
						|
 | 
						|
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_X<Principal_Largeur_image)
 | 
						|
        && (Pinceau_Y<Principal_Hauteur_image) )
 | 
						|
        Pipette_Couleur=Lit_pixel_dans_ecran_courant(Pinceau_X,Pinceau_Y);
 | 
						|
      else
 | 
						|
        Pipette_Couleur=0;
 | 
						|
      Pipette_X=Pinceau_X;
 | 
						|
      Pipette_Y=Pinceau_Y;
 | 
						|
 | 
						|
      Num2str(Pipette_Couleur,Tempo,3);
 | 
						|
      Print_dans_menu(Tempo,20);
 | 
						|
      Print_general(170*Menu_Facteur_X,Menu_Ordonnee_Texte," ",0,Pipette_Couleur);
 | 
						|
    }
 | 
						|
 | 
						|
    Num2str((dword)Pinceau_X,Tempo,4);
 | 
						|
    Print_dans_menu(Tempo,2);
 | 
						|
    Num2str((dword)Pinceau_Y,Tempo,4);
 | 
						|
    Print_dans_menu(Tempo,11);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
  // -- Afficher le nom du fichier dans le menu --
 | 
						|
 | 
						|
void Print_nom_fichier(void)
 | 
						|
{
 | 
						|
  short Debut_X;
 | 
						|
  
 | 
						|
  if (Menu_visible)
 | 
						|
  {
 | 
						|
    // Si le nom de fichier fait plus de 12 caractères, on n'affiche que les 12 derniers
 | 
						|
    char * Nom_affiche = Principal_Nom_fichier;
 | 
						|
    int Taille_nom =strlen(Principal_Nom_fichier);
 | 
						|
    if (Taille_nom>12)
 | 
						|
    {
 | 
						|
      Nom_affiche=Principal_Nom_fichier + Taille_nom - 12;
 | 
						|
      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);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// -- 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 (C<Debut)
 | 
						|
      switch (Quick_shade_Loop)
 | 
						|
      {
 | 
						|
        case MODE_SHADE_NORMAL : return Debut;
 | 
						|
        case MODE_SHADE_BOUCLE : return (Largeur+C);
 | 
						|
        default : return Couleur;
 | 
						|
      }
 | 
						|
 | 
						|
    if (C>Fin)
 | 
						|
      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)<Principal_Largeur_image);
 | 
						|
  byte Y2=((Y+1)<Principal_Hauteur_image);
 | 
						|
 | 
						|
  // On commence par le pixel central
 | 
						|
  C=Lit_pixel_dans_ecran_feedback(X,Y);
 | 
						|
  Poids_total=Smooth_Matrice[1][1];
 | 
						|
  R=Poids_total*Principal_Palette[C].R;
 | 
						|
  V=Poids_total*Principal_Palette[C].V;
 | 
						|
  B=Poids_total*Principal_Palette[C].B;
 | 
						|
 | 
						|
  if (X)
 | 
						|
  {
 | 
						|
    C=Lit_pixel_dans_ecran_feedback(X-1,Y);
 | 
						|
    Poids_total+=(Poids=Smooth_Matrice[0][1]);
 | 
						|
    R+=Poids*Principal_Palette[C].R;
 | 
						|
    V+=Poids*Principal_Palette[C].V;
 | 
						|
    B+=Poids*Principal_Palette[C].B;
 | 
						|
 | 
						|
    if (Y)
 | 
						|
    {
 | 
						|
      C=Lit_pixel_dans_ecran_feedback(X-1,Y-1);
 | 
						|
      Poids_total+=(Poids=Smooth_Matrice[0][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-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;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (X2)
 | 
						|
  {
 | 
						|
    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)
 | 
						|
    {
 | 
						|
      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)
 | 
						|
      {
 | 
						|
        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 (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;
 | 
						|
  }
 | 
						|
 | 
						|
  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.
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// -- Fonctions de manipulation du pinceau -----------------------------------
 | 
						|
 | 
						|
  // -- 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_Gauche)
 | 
						|
  {
 | 
						|
    (*Largeur)-=(Limite_Gauche-(*X));
 | 
						|
    (*X)=Limite_Gauche;
 | 
						|
  }
 | 
						|
 | 
						|
  if (((*X)+(*Largeur))>(Limite_Droite+1))
 | 
						|
  {
 | 
						|
    (*Largeur)=(Limite_Droite-(*X))+1;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((*Y)<Limite_Haut)
 | 
						|
  {
 | 
						|
    (*Hauteur)-=(Limite_Haut-(*Y));
 | 
						|
    (*Y)=Limite_Haut;
 | 
						|
  }
 | 
						|
 | 
						|
  if (((*Y)+(*Hauteur))>(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_Gauche_Zoom)
 | 
						|
  {
 | 
						|
    (*Largeur)-=(Limite_Gauche_Zoom-(*X));
 | 
						|
    (*X)=Limite_Gauche_Zoom;
 | 
						|
  }
 | 
						|
 | 
						|
  if (((*X)+(*Largeur))>(Limite_Droite_Zoom+1))
 | 
						|
  {
 | 
						|
    (*Largeur)=(Limite_Droite_Zoom-(*X))+1;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((*Y)<Limite_Haut_Zoom)
 | 
						|
  {
 | 
						|
    (*Hauteur)-=(Limite_Haut_Zoom-(*Y));
 | 
						|
    (*Y)=Limite_Haut_Zoom;
 | 
						|
  }
 | 
						|
 | 
						|
  if (((*Y)+(*Hauteur))>(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_Max_Y) && (Compteur_X<Smear_Max_X)
 | 
						|
                  && (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_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_brosse(Compteur_X,Compteur_Y);
 | 
						|
                if (Couleur_temporaire!=Back_color)
 | 
						|
                  Afficher_pixel(Pos_X,Pos_Y,Couleur_temporaire);
 | 
						|
              }
 | 
						|
          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++)
 | 
						|
              {
 | 
						|
                if (Lit_pixel_dans_brosse(Compteur_X,Compteur_Y)!=Back_color)
 | 
						|
                  Afficher_pixel(Pos_X,Pos_Y,Couleur);
 | 
						|
              }
 | 
						|
        }
 | 
						|
	Mettre_Ecran_A_Jour(Debut_X,Debut_Y,Fin_Compteur_X,Fin_Compteur_Y);
 | 
						|
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    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 (Preview)
 | 
						|
      {
 | 
						|
        if ( (Largeur>0) && (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<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_Max_Y) && (Compteur_X<Smear_Max_X)
 | 
						|
                  && (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_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++)
 | 
						|
            {
 | 
						|
              if (Lit_pixel_dans_brosse(Compteur_X,Compteur_Y)!=Back_color)
 | 
						|
                Afficher_pixel(Pos_X,Pos_Y,Couleur);
 | 
						|
            }
 | 
						|
          Mettre_Ecran_A_Jour(Debut_X,Debut_Y,Fin_Compteur_X-Debut_Compteur_X,Fin_Compteur_Y-Debut_Compteur_Y);
 | 
						|
        }
 | 
						|
      }
 | 
						|
	Mettre_Ecran_A_Jour(X-Brosse_Decalage_X,Y-Brosse_Decalage_Y,Brosse_Largeur,Brosse_Hauteur);
 | 
						|
      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;
 | 
						|
      if (Preview)
 | 
						|
      {
 | 
						|
        Temp=Brosse;
 | 
						|
        Brosse=Pinceau_Sprite;
 | 
						|
 | 
						|
        if ( (Largeur>0) && (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<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 ( (Pinceau_Sprite[(TAILLE_MAXI_PINCEAU*Compteur_Y)+Compteur_X])
 | 
						|
                  && (Compteur_Y<Smear_Max_Y) && (Compteur_X<Smear_Max_X)
 | 
						|
                  && (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<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++)
 | 
						|
            {
 | 
						|
              if (Pinceau_Sprite[(TAILLE_MAXI_PINCEAU*Compteur_Y)+Compteur_X])
 | 
						|
                Afficher_pixel(Pos_X,Pos_Y,Couleur);
 | 
						|
            }
 | 
						|
	        Mettre_Ecran_A_Jour(X,Y,Largeur,Hauteur);
 | 
						|
        }
 | 
						|
      }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// -- Effacer le pinceau -- //
 | 
						|
//
 | 
						|
void Effacer_pinceau(short X,short Y)
 | 
						|
  // X,Y: position du centre du pinceau
 | 
						|
{
 | 
						|
  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 * Temp;
 | 
						|
 | 
						|
  if (!Mouse_K)
 | 
						|
  switch (Pinceau_Forme)
 | 
						|
  {
 | 
						|
    case FORME_PINCEAU_POINT :
 | 
						|
      if ( (Pinceau_X>=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<Menu_Ordonnee)?Pos_Y_reelle+Loupe_Facteur:Menu_Ordonnee;
 | 
						|
  short Indice;
 | 
						|
 | 
						|
  for (Indice=Pos_Y_reelle; Indice<Pos_Y_Fin; Indice++)
 | 
						|
    Ligne_horizontale_XOR(Pos_X_reelle,Indice,Largeur_reelle);
 | 
						|
 | 
						|
  UpdateRect(Pos_X_reelle,Pos_Y_reelle,Largeur_reelle,Pos_Y_Fin-Pos_Y_reelle);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
  // -- Afficher une barre verticale XOR zoomée
 | 
						|
 | 
						|
void Ligne_verticale_XOR_Zoom(short Pos_X, short Pos_Y, short Hauteur)
 | 
						|
{
 | 
						|
  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 Pos_Y_Fin=(Pos_Y_reelle+(Hauteur*Loupe_Facteur<Menu_Ordonnee))?Pos_Y_reelle+(Hauteur*Loupe_Facteur):Menu_Ordonnee;
 | 
						|
  short Indice;
 | 
						|
 | 
						|
  for (Indice=Pos_Y_reelle; Indice<Pos_Y_Fin; Indice++)
 | 
						|
    Ligne_horizontale_XOR(Pos_X_reelle,Indice,Loupe_Facteur);
 | 
						|
 | 
						|
  UpdateRect(Pos_X_reelle,Pos_Y_reelle,Loupe_Facteur,Pos_Y_Fin-Pos_Y_reelle);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
  // -- Afficher le curseur --
 | 
						|
 | 
						|
void Afficher_curseur(void)
 | 
						|
{
 | 
						|
  byte  Forme;
 | 
						|
  short Debut_X;
 | 
						|
  short Debut_Y;
 | 
						|
  short Fin_X;
 | 
						|
  short Fin_Y;
 | 
						|
  short Pos_X;
 | 
						|
  short 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<Menu_Ordonnee)
 | 
						|
      && ( (!Loupe_Mode) || (Mouse_X<Principal_Split) || (Mouse_X>=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<Largeur_ecran-6)
 | 
						|
            Ligne_verticale_XOR  (Mouse_X+6,Debut_Y+Mouse_Y-1,3-(Debut_Y+Fin_Y));
 | 
						|
 | 
						|
          if (Mouse_Y<Menu_Ordonnee-6)
 | 
						|
            Ligne_horizontale_XOR(Debut_X+Mouse_X-1,Mouse_Y+6,3-(Debut_X+Fin_X));
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          Temp=(Config.Curseur)?FORME_CURSEUR_CIBLE_PIPETTE_FINE:FORME_CURSEUR_CIBLE_PIPETTE;
 | 
						|
          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++)
 | 
						|
            for (Pos_Y=Debut_Y,Compteur_Y=0;Compteur_Y<15;Pos_Y++,Compteur_Y++)
 | 
						|
            {
 | 
						|
              Couleur=SPRITE_CURSEUR[Temp][Compteur_Y][Compteur_X];
 | 
						|
              if ( (Pos_X>=0) && (Pos_X<Largeur_ecran)
 | 
						|
                && (Pos_Y>=0) && (Pos_Y<Hauteur_ecran) )
 | 
						|
              {
 | 
						|
                FOND_CURSEUR[Compteur_Y][Compteur_X]=Lit_pixel(Pos_X,Pos_Y);
 | 
						|
                if (Couleur!=CM_Trans)
 | 
						|
                  Pixel(Pos_X,Pos_Y,Couleur);
 | 
						|
              }
 | 
						|
            }
 | 
						|
          UpdateRect(Debut_X,Debut_Y,16,16);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case FORME_CURSEUR_MULTIDIRECTIONNEL :
 | 
						|
    case FORME_CURSEUR_HORIZONTAL :
 | 
						|
      if (Cacher_curseur)
 | 
						|
        break;
 | 
						|
 | 
						|
    case FORME_CURSEUR_FLECHE :
 | 
						|
    case FORME_CURSEUR_SABLIER :
 | 
						|
      Debut_X=Mouse_X-Curseur_Decalage_X[Forme];
 | 
						|
      Debut_Y=Mouse_Y-Curseur_Decalage_Y[Forme];
 | 
						|
      for (Pos_X=Debut_X,Compteur_X=0;Compteur_X<15;Pos_X++,Compteur_X++)
 | 
						|
      {
 | 
						|
	if(Pos_X<0) continue;
 | 
						|
	if(Pos_X>=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<Menu_Ordonnee) && (Pinceau_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<Compteur_X) && (Pinceau_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<Menu_Ordonnee)
 | 
						|
      && ( (!Loupe_Mode) || (Mouse_X<Principal_Split) 
 | 
						|
                         || (Mouse_X>=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<Largeur_ecran-6)
 | 
						|
            Ligne_verticale_XOR  (Mouse_X+6,Debut_Y+Mouse_Y-1,3-(Debut_Y+Fin_Y));
 | 
						|
 | 
						|
          if (Mouse_Y<Menu_Ordonnee-6)
 | 
						|
            Ligne_horizontale_XOR(Debut_X+Mouse_X-1,Mouse_Y+6,3-(Debut_X+Fin_X));
 | 
						|
 | 
						|
          UpdateRect(Debut_X,Debut_Y,Fin_X-Debut_X,Fin_Y-Debut_Y);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          Temp=(Config.Curseur)?FORME_CURSEUR_CIBLE_PIPETTE_FINE:FORME_CURSEUR_CIBLE_PIPETTE;
 | 
						|
          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++)
 | 
						|
            for (Pos_Y=Debut_Y,Compteur_Y=0;Compteur_Y<15;Pos_Y++,Compteur_Y++)
 | 
						|
              if ( (Pos_X>=0) && (Pos_X<Largeur_ecran) && (Pos_Y>=0) && (Pos_Y<Hauteur_ecran) )
 | 
						|
                Pixel(Pos_X,Pos_Y,FOND_CURSEUR[Compteur_Y][Compteur_X]);
 | 
						|
 | 
						|
          UpdateRect(Max(Debut_X,0),Max(Debut_Y,0),16,16);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (!Cacher_pinceau)
 | 
						|
        Effacer_pinceau(Pinceau_X,Pinceau_Y);
 | 
						|
      break;
 | 
						|
      
 | 
						|
    case FORME_CURSEUR_MULTIDIRECTIONNEL :
 | 
						|
    case FORME_CURSEUR_HORIZONTAL :
 | 
						|
      if (Cacher_curseur)
 | 
						|
        break;
 | 
						|
 | 
						|
    case FORME_CURSEUR_FLECHE :
 | 
						|
    case FORME_CURSEUR_SABLIER :
 | 
						|
      Debut_X=Mouse_X-Curseur_Decalage_X[Forme];
 | 
						|
      Debut_Y=Mouse_Y-Curseur_Decalage_Y[Forme];
 | 
						|
 | 
						|
      for (Pos_X=Debut_X,Compteur_X=0;Compteur_X<15;Pos_X++,Compteur_X++)
 | 
						|
      {
 | 
						|
	if(Pos_X<0) continue;
 | 
						|
	if(Pos_X>=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<Menu_Ordonnee) && (Pinceau_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<Compteur_X) && (Pinceau_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<Principal_Split)
 | 
						|
      Largeur=Principal_Largeur_image;
 | 
						|
    else
 | 
						|
      Largeur=Principal_Split;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (Principal_Largeur_image<Largeur_ecran)
 | 
						|
      Largeur=Principal_Largeur_image;
 | 
						|
    else
 | 
						|
      Largeur=Largeur_ecran;
 | 
						|
  }
 | 
						|
  if (Principal_Hauteur_image<Menu_Ordonnee)
 | 
						|
    Hauteur=Principal_Hauteur_image;
 | 
						|
  else
 | 
						|
    Hauteur=Menu_Ordonnee;
 | 
						|
  Display_screen(Largeur,Hauteur,Principal_Largeur_image);
 | 
						|
 | 
						|
  // Effacement de la partie non-image dans la partie non zoomée:
 | 
						|
  if (Loupe_Mode)
 | 
						|
  {
 | 
						|
    if (Principal_Largeur_image<Principal_Split && Principal_Largeur_image < Largeur_ecran)
 | 
						|
      Block(Principal_Largeur_image,0,(Principal_Split-Principal_Largeur_image),Menu_Ordonnee,0);
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (Principal_Largeur_image<Largeur_ecran)
 | 
						|
      Block(Principal_Largeur_image,0,(Largeur_ecran-Principal_Largeur_image),Menu_Ordonnee,0);
 | 
						|
  }
 | 
						|
  if (Principal_Hauteur_image<Menu_Ordonnee)
 | 
						|
    Block(0,Principal_Hauteur_image,Largeur,(Menu_Ordonnee-Hauteur),0);
 | 
						|
 | 
						|
  // ---/\/\/\  Partie zoomée: /\/\/\---
 | 
						|
  if (Loupe_Mode)
 | 
						|
  {
 | 
						|
    // Affichage de la barre de split
 | 
						|
    Afficher_barre_de_split();
 | 
						|
 | 
						|
    // Calcul de la largeur visible
 | 
						|
    if (Principal_Largeur_image<Loupe_Largeur)
 | 
						|
      Largeur=Principal_Largeur_image;
 | 
						|
    else
 | 
						|
      Largeur=Loupe_Largeur;
 | 
						|
 | 
						|
    // Calcul du nombre de lignes visibles de l'image zoomée
 | 
						|
    if (Principal_Hauteur_image<Loupe_Hauteur)
 | 
						|
      Hauteur=Principal_Hauteur_image*Loupe_Facteur;
 | 
						|
    else
 | 
						|
      Hauteur=Menu_Ordonnee;
 | 
						|
 | 
						|
    Display_zoomed_screen(Largeur,Hauteur,Principal_Largeur_image,Buffer_de_ligne_horizontale);
 | 
						|
 | 
						|
    // Effacement de la partie non-image dans la partie zoomée:
 | 
						|
    if (Principal_Largeur_image<Loupe_Largeur)
 | 
						|
      Block(Principal_X_Zoom+(Principal_Largeur_image*Loupe_Facteur),0,
 | 
						|
            (Loupe_Largeur-Principal_Largeur_image)*Loupe_Facteur,
 | 
						|
            Menu_Ordonnee,0);
 | 
						|
    if (Principal_Hauteur_image<Loupe_Hauteur)
 | 
						|
      Block(Principal_X_Zoom,Hauteur,Largeur*Loupe_Facteur,(Menu_Ordonnee-Hauteur),0);
 | 
						|
  }
 | 
						|
 | 
						|
  // ---/\/\/\ Affichage des limites /\/\/\---
 | 
						|
  if (Config.Afficher_limites_image)
 | 
						|
    Afficher_limites_de_l_image();
 | 
						|
  UpdateRect(0,0,Largeur_ecran,Menu_Ordonnee); // TODO On peut faire plus fin, en évitant de mettre à jour la partie à droite du split quand on est en mode loupe. Mais c'est pas vraiment intéressant ?
 | 
						|
}
 | 
						|
 | 
						|
  // -- 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<HAUTEUR_SPRITE_MENU;Pos_Y++,Pos_menu_Y++)
 | 
						|
    for (Pos_X=0,Pos_menu_X=Bouton[Numero_bouton].Decalage_X+1;Pos_X<LARGEUR_SPRITE_MENU;Pos_X++,Pos_menu_X++)
 | 
						|
    {
 | 
						|
      Couleur=SPRITE_MENU[Numero_sprite][Pos_Y][Pos_X];
 | 
						|
      Pixel_dans_menu(Pos_menu_X,Pos_menu_Y,Couleur);
 | 
						|
      BLOCK_MENU[Pos_menu_Y][Pos_menu_X]=Couleur;
 | 
						|
    }
 | 
						|
  UpdateRect(Menu_Facteur_X*(Bouton[Numero_bouton].Decalage_X+1),
 | 
						|
    (Bouton[Numero_bouton].Decalage_Y+1)*Menu_Facteur_Y+Menu_Ordonnee,
 | 
						|
    LARGEUR_SPRITE_MENU*Menu_Facteur_X,HAUTEUR_SPRITE_MENU*Menu_Facteur_Y);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Redessiner la forme du pinceau dans le menu --
 | 
						|
 | 
						|
void Afficher_pinceau_dans_menu(void)
 | 
						|
{
 | 
						|
  short Pos_X,Pos_Y;
 | 
						|
  short Debut_X;
 | 
						|
  short Pos_menu_X,Pos_menu_Y;
 | 
						|
  short Debut_menu_X;
 | 
						|
  byte Couleur;
 | 
						|
 | 
						|
  switch (Pinceau_Forme)
 | 
						|
  {
 | 
						|
    case FORME_PINCEAU_BROSSE_COULEUR    : // Brosse en couleur
 | 
						|
    case FORME_PINCEAU_BROSSE_MONOCHROME : // Brosse monochrome
 | 
						|
      for (Pos_menu_Y=2,Pos_Y=0;Pos_Y<HAUTEUR_SPRITE_MENU;Pos_menu_Y++,Pos_Y++)
 | 
						|
        for (Pos_menu_X=1,Pos_X=0;Pos_X<LARGEUR_SPRITE_MENU;Pos_menu_X++,Pos_X++)
 | 
						|
        {
 | 
						|
          Couleur=SPRITE_MENU[3][Pos_Y][Pos_X];
 | 
						|
          Pixel_dans_menu(Pos_menu_X,Pos_menu_Y,Couleur);
 | 
						|
          BLOCK_MENU[Pos_menu_Y][Pos_menu_X]=Couleur;
 | 
						|
        }
 | 
						|
      break;
 | 
						|
    default : // Pinceau
 | 
						|
      // On efface le pinceau précédent
 | 
						|
      for (Pos_menu_Y=2,Pos_Y=0;Pos_Y<HAUTEUR_SPRITE_MENU;Pos_menu_Y++,Pos_Y++)
 | 
						|
        for (Pos_menu_X=1,Pos_X=0;Pos_X<LARGEUR_SPRITE_MENU;Pos_menu_X++,Pos_X++)
 | 
						|
        {
 | 
						|
          Pixel_dans_menu(Pos_menu_X,Pos_menu_Y,CM_Clair);
 | 
						|
          BLOCK_MENU[Pos_menu_Y][Pos_menu_X]=CM_Clair;
 | 
						|
        }
 | 
						|
      // On affiche le nouveau
 | 
						|
      Debut_menu_X=8-Pinceau_Decalage_X;
 | 
						|
      if (Debut_menu_X<1)
 | 
						|
      {
 | 
						|
        Debut_X=Pinceau_Decalage_X-7;
 | 
						|
        Debut_menu_X=1;
 | 
						|
      }
 | 
						|
      else
 | 
						|
        Debut_X=0;
 | 
						|
 | 
						|
      Pos_menu_Y=9-Pinceau_Decalage_Y;
 | 
						|
      if (Pos_menu_Y<2)
 | 
						|
      {
 | 
						|
        Pos_Y=Pinceau_Decalage_Y-7;
 | 
						|
        Pos_menu_Y=2;
 | 
						|
      }
 | 
						|
      else
 | 
						|
        Pos_Y=0;
 | 
						|
 | 
						|
      for (;((Pos_Y<Pinceau_Hauteur) && (Pos_menu_Y<16));Pos_menu_Y++,Pos_Y++)
 | 
						|
        for (Pos_menu_X=Debut_menu_X,Pos_X=Debut_X;((Pos_X<Pinceau_Largeur) && (Pos_menu_X<15));Pos_menu_X++,Pos_X++)
 | 
						|
        {
 | 
						|
          Couleur=(Pinceau_Sprite[(Pos_Y*TAILLE_MAXI_PINCEAU)+Pos_X])?CM_Noir:CM_Clair;
 | 
						|
          Pixel_dans_menu(Pos_menu_X,Pos_menu_Y,Couleur);
 | 
						|
          BLOCK_MENU[Pos_menu_Y][Pos_menu_X]=Couleur;
 | 
						|
        }
 | 
						|
  }
 | 
						|
  UpdateRect(0,Menu_Ordonnee,LARGEUR_SPRITE_MENU*Menu_Facteur_X+3,HAUTEUR_SPRITE_MENU*Menu_Facteur_Y+3);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Dessiner un pinceau prédéfini dans la fenêtre --
 | 
						|
 | 
						|
void Afficher_pinceau_dans_fenetre(word X,word Y,int Numero)
 | 
						|
  // Pinceau = 0..NB_SPRITES_PINCEAU-1 : Pinceau prédéfini
 | 
						|
{
 | 
						|
  word Pos_X;
 | 
						|
  word Pos_Y;
 | 
						|
  word Pos_fenetre_X;
 | 
						|
  word Pos_fenetre_Y;
 | 
						|
 | 
						|
  word Orig_X = X + 8 - Pinceau_predefini_Decalage_X[Numero];
 | 
						|
  word Orig_Y = Y + 8 - Pinceau_predefini_Decalage_Y[Numero];
 | 
						|
 | 
						|
  for (Pos_fenetre_Y=Orig_Y,Pos_Y=0; Pos_Y<Pinceau_predefini_Hauteur[Numero]; Pos_fenetre_Y++,Pos_Y++)
 | 
						|
    for (Pos_fenetre_X=Orig_X,Pos_X=0; Pos_X<Pinceau_predefini_Largeur[Numero]; Pos_fenetre_X++,Pos_X++)
 | 
						|
      Pixel_dans_fenetre(Pos_fenetre_X,Pos_fenetre_Y,(SPRITE_PINCEAU[Numero][Pos_Y][Pos_X])?CM_Noir:CM_Clair);
 | 
						|
 | 
						|
  UpdateRect( ToWinX(Orig_X), ToWinY(Orig_Y),
 | 
						|
        ToWinL(Pinceau_predefini_Largeur[Numero]), 
 | 
						|
        ToWinH(Pinceau_predefini_Hauteur[Numero])
 | 
						|
  );
 | 
						|
}
 | 
						|
 | 
						|
  // -- Dessiner des zigouigouis --
 | 
						|
 | 
						|
void Dessiner_zigouigoui(word X,word Y, byte Couleur, short Sens)
 | 
						|
{
 | 
						|
  word i;
 | 
						|
 | 
						|
  for (i=0; i<11; i++) Pixel_dans_fenetre(X,Y+i,Couleur);
 | 
						|
  X+=Sens;
 | 
						|
  for (i=1; i<10; i++) Pixel_dans_fenetre(X,Y+i,Couleur);
 | 
						|
  X+=Sens+Sens;
 | 
						|
  for (i=3; i<8; i++) Pixel_dans_fenetre(X,Y+i,Couleur);
 | 
						|
  X+=Sens+Sens;
 | 
						|
  Pixel_dans_fenetre(X,Y+5,Couleur);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Dessiner un bloc de couleurs dégradé verticalement
 | 
						|
 | 
						|
void Bloc_degrade_dans_fenetre(word Pos_X,word Pos_Y,word Debut_block,word Fin_block)
 | 
						|
{
 | 
						|
  word Total_lignes  =Menu_Facteur_Y<<6; // <=> à 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<Fin_Y;Indice++,Ligne_en_cours++)
 | 
						|
    Block(Debut_X,Indice,Largeur_ligne,1,Debut_block+(Nb_couleurs*Ligne_en_cours)/Total_lignes);
 | 
						|
 | 
						|
  UpdateRect(ToWinX(Pos_X),ToWinY(Pos_Y),ToWinL(16),ToWinH(64));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
  // -- Redimentionner l'image (nettoie l'écran virtuel) --
 | 
						|
 | 
						|
void Redimentionner_image(word Largeur_choisie,word Hauteur_choisie)
 | 
						|
{
 | 
						|
  word Ancienne_largeur=Principal_Largeur_image;
 | 
						|
  word Ancienne_hauteur=Principal_Hauteur_image;
 | 
						|
 | 
						|
  // +-+-+
 | 
						|
  // |C| |  A+B+C = Ancienne image
 | 
						|
  // +-+A|
 | 
						|
  // |B| |    C   = Nouvelle image
 | 
						|
  // +-+-+
 | 
						|
 | 
						|
  if (Backup_avec_nouvelles_dimensions(1,Largeur_choisie,Hauteur_choisie))
 | 
						|
  {
 | 
						|
    // La nouvelle page a pu être allouée, elle est pour l'instant pleine de
 | 
						|
    // 0s. Elle fait Principal_Largeur_image de large.
 | 
						|
 | 
						|
    // On copie donc maintenant la partie C dans la nouvelle image.
 | 
						|
    Copier_une_partie_d_image_dans_une_autre(
 | 
						|
      Ecran_backup,0,0,Min(Ancienne_largeur,Principal_Largeur_image),
 | 
						|
      Min(Ancienne_hauteur,Principal_Hauteur_image),Ancienne_largeur,
 | 
						|
      Principal_Ecran,0,0,Principal_Largeur_image);
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    // Afficher un message d'erreur
 | 
						|
    Afficher_curseur();
 | 
						|
    Message_Memoire_insuffisante();
 | 
						|
    Effacer_curseur();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
  // -- Dessiner un petit sprite représentant le type d'un drive --
 | 
						|
 | 
						|
void Fenetre_Afficher_sprite_drive(word Pos_X,word Pos_Y,byte Type)
 | 
						|
{
 | 
						|
  word i,j;
 | 
						|
 | 
						|
  for (j=0; j<HAUTEUR_SPRITE_DRIVE; j++)
 | 
						|
    for (i=0; i<LARGEUR_SPRITE_DRIVE; i++)
 | 
						|
      Pixel_dans_fenetre(Pos_X+i,Pos_Y+j,SPRITE_DRIVE[Type][j][i]);
 | 
						|
  UpdateRect(ToWinX(Pos_X),ToWinY(Pos_Y),ToWinL(LARGEUR_SPRITE_DRIVE),ToWinH(HAUTEUR_SPRITE_DRIVE));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
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_X<Principal_Largeur_image) && (Debut_Y<Principal_Hauteur_image))
 | 
						|
  {
 | 
						|
    // On met les décalages du tiling à 0 pour eviter toute incohérence.
 | 
						|
    // Si par hasard on voulait les mettre à
 | 
						|
    //    min(Tiling_Decalage_?,Brosse_?a??eur-1)
 | 
						|
    // il faudrait penser à les initialiser à 0 dans "MAIN.C".
 | 
						|
    Tiling_Decalage_X=0;
 | 
						|
    Tiling_Decalage_Y=0;
 | 
						|
 | 
						|
    // Ensuite, on calcule les dimensions de la brosse:
 | 
						|
    Nouvelle_Brosse_Largeur=(Fin_X-Debut_X)+1;
 | 
						|
    Nouvelle_Brosse_Hauteur=(Fin_Y-Debut_Y)+1;
 | 
						|
 | 
						|
    if (Debut_X+Nouvelle_Brosse_Largeur>Principal_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<Debut_Y+Brosse_Hauteur;Pos_Y++)
 | 
						|
        for (Pos_X=Debut_X;Pos_X<Debut_X+Brosse_Largeur;Pos_X++)
 | 
						|
        {
 | 
						|
          Pixel_dans_ecran_courant(Pos_X,Pos_Y,Back_color);
 | 
						|
          Pixel_Preview           (Pos_X,Pos_Y,Back_color);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // On centre la prise sur la brosse
 | 
						|
    Brosse_Decalage_X=(Brosse_Largeur>>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<Brosse_Hauteur;Pos_Y++)
 | 
						|
    for (Pos_X=0;Pos_X<Brosse_Largeur;Pos_X++)
 | 
						|
      Utilisee[Lit_pixel_dans_brosse(Pos_X,Pos_Y)]=1;
 | 
						|
 | 
						|
  //  On n'est pas censé remapper la couleur de transparence, sinon la brosse
 | 
						|
  // changera de forme, donc on dit pour l'instant qu'elle n'est pas utilisée
 | 
						|
  // ainsi on ne s'embêtera pas à la recalculer
 | 
						|
  Utilisee[Back_color]=0;
 | 
						|
 | 
						|
  //   On va maintenant se servir de la table "Utilisee" comme table de
 | 
						|
  // conversion: pour chaque indice, la table donne une couleur de
 | 
						|
  // remplacement.
 | 
						|
  // Note : Seules les couleurs utilisées on besoin d'êtres recalculées: les
 | 
						|
  //       autres ne seront jamais consultées dans la nouvelle table de
 | 
						|
  //       conversion puisque elles n'existent pas dans la brosse, donc elles
 | 
						|
  //       ne seront pas utilisées par Remap_brush_LOWLEVEL.
 | 
						|
  for (Couleur=0;Couleur<=255;Couleur++)
 | 
						|
    if (Utilisee[Couleur])
 | 
						|
      Utilisee[Couleur]=Meilleure_couleur(Brouillon_Palette[Couleur].R,Brouillon_Palette[Couleur].V,Brouillon_Palette[Couleur].B);
 | 
						|
 | 
						|
  //   Il reste une couleur non calculée dans la table qu'il faut mettre à
 | 
						|
  // jour: c'est la couleur de fond. On l'avait inhibée pour éviter son
 | 
						|
  // calcul inutile, mais comme il est possible qu'elle soit quand même dans
 | 
						|
  // la brosse, on va mettre dans la table une relation d'équivalence entre
 | 
						|
  // les deux palettes: comme on ne veut pas que la couleur soit remplacée,
 | 
						|
  // on va dire qu'on veut qu'elle soit remplacée par la couleur en question.
 | 
						|
  Utilisee[Back_color]=Back_color;
 | 
						|
 | 
						|
  //   Maintenant qu'on a une super table de conversion qui n'a que le nom
 | 
						|
  // qui craint un peu, on peut faire l'échange dans la brosse de toutes les
 | 
						|
  // teintes.
 | 
						|
  Remap_general_LOWLEVEL(Utilisee,Brosse,Brosse_Largeur,Brosse_Hauteur,Brosse_Largeur);
 | 
						|
  //Remap_brush_LOWLEVEL(Utilisee);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void Remap_picture(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<Brouillon_Hauteur_image;Pos_Y++)
 | 
						|
    for (Pos_X=0;Pos_X<Brouillon_Largeur_image;Pos_X++)
 | 
						|
      Utilisee[Lit_pixel_dans_ecran_brouillon(Pos_X,Pos_Y)]=1;
 | 
						|
 | 
						|
  //   On va maintenant se servir de la table "Utilisee" comme table de
 | 
						|
  // conversion: pour chaque indice, la table donne une couleur de
 | 
						|
  // remplacement.
 | 
						|
  // Note : Seules les couleurs utilisées on besoin d'êtres recalculées: les
 | 
						|
  //       autres ne seront jamais consultées dans la nouvelle table de
 | 
						|
  //       conversion puisque elles n'existent pas dans l'image, donc elles
 | 
						|
  //       ne seront pas utilisées par Remap_general_LOWLEVEL.
 | 
						|
  for (Couleur=0;Couleur<=255;Couleur++)
 | 
						|
    if (Utilisee[Couleur])
 | 
						|
      Utilisee[Couleur]=Meilleure_couleur(Brouillon_Palette[Couleur].R,Brouillon_Palette[Couleur].V,Brouillon_Palette[Couleur].B);
 | 
						|
 | 
						|
  //   Maintenant qu'on a une super table de conversion qui n'a que le nom
 | 
						|
  // qui craint un peu, on peut faire l'échange dans la brosse de toutes les
 | 
						|
  // teintes.
 | 
						|
  Remap_general_LOWLEVEL(Utilisee,Brouillon_Ecran,Brouillon_Largeur_image,Brouillon_Hauteur_image,Brouillon_Largeur_image);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void Get_colors_from_brush(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;
 | 
						|
 | 
						|
  if (Demande_de_confirmation("Modify current palette ?"))
 | 
						|
  {
 | 
						|
    Backup();
 | 
						|
 | 
						|
    // On commence par initialiser le tableau de booléen à faux
 | 
						|
    for (Couleur=0;Couleur<=255;Couleur++)
 | 
						|
      Utilisee[Couleur]=0;
 | 
						|
 | 
						|
    // On calcule la table d'utilisation des couleurs
 | 
						|
    for (Pos_Y=0;Pos_Y<Brosse_Hauteur;Pos_Y++)
 | 
						|
      for (Pos_X=0;Pos_X<Brosse_Largeur;Pos_X++)
 | 
						|
        Utilisee[Lit_pixel_dans_brosse(Pos_X,Pos_Y)]=1;
 | 
						|
 | 
						|
    // On recopie dans la palette principale les teintes des couleurs utilisées
 | 
						|
    // dans la palette du brouillon
 | 
						|
    for (Couleur=0;Couleur<=255;Couleur++)
 | 
						|
      if (Utilisee[Couleur])
 | 
						|
      {
 | 
						|
        Principal_Palette[Couleur].R=Brouillon_Palette[Couleur].R;
 | 
						|
        Principal_Palette[Couleur].V=Brouillon_Palette[Couleur].V;
 | 
						|
        Principal_Palette[Couleur].B=Brouillon_Palette[Couleur].B;
 | 
						|
      }
 | 
						|
 | 
						|
    Set_palette(Principal_Palette);
 | 
						|
    Calculer_couleurs_menu_optimales(Principal_Palette);
 | 
						|
    Effacer_curseur();
 | 
						|
    Afficher_ecran();
 | 
						|
    Afficher_menu();
 | 
						|
    Afficher_curseur();
 | 
						|
 | 
						|
    Principal_Image_modifiee=1;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void Outline_brush(void)
 | 
						|
{
 | 
						|
  long /*Pos,*/Pos_X,Pos_Y;
 | 
						|
  byte Etat;
 | 
						|
  byte * Nouvelle_brosse;
 | 
						|
  byte * Temporaire;
 | 
						|
  word Largeur;
 | 
						|
  word Hauteur;
 | 
						|
 | 
						|
 | 
						|
  Largeur=Brosse_Largeur+2;
 | 
						|
  Hauteur=Brosse_Hauteur+2;
 | 
						|
  Nouvelle_brosse=(byte *)malloc(((long)Largeur)*Hauteur);
 | 
						|
 | 
						|
  if (Nouvelle_brosse)
 | 
						|
  {
 | 
						|
    // On remplit la bordure ajoutée par la Backcolor
 | 
						|
    memset(Nouvelle_brosse,Back_color,((long)Largeur)*Hauteur);
 | 
						|
 | 
						|
    // On copie la brosse courante dans la nouvelle
 | 
						|
    Copier_une_partie_d_image_dans_une_autre(Brosse, // Source
 | 
						|
                                             0, 0,
 | 
						|
                                             Brosse_Largeur,
 | 
						|
                                             Brosse_Hauteur,
 | 
						|
                                             Brosse_Largeur,
 | 
						|
                                             Nouvelle_brosse, // Destination
 | 
						|
                                             1, 1,
 | 
						|
                                             Largeur);
 | 
						|
 | 
						|
    // On intervertit la nouvelle et l'ancienne brosse:
 | 
						|
    Temporaire=Brosse;
 | 
						|
    Brosse=Nouvelle_brosse;
 | 
						|
    Brosse_Largeur+=2;
 | 
						|
    Brosse_Hauteur+=2;
 | 
						|
    Largeur-=2;
 | 
						|
    Hauteur-=2;
 | 
						|
 | 
						|
    // Si on "outline" avec une couleur différente de la Back_color on y va!
 | 
						|
    if (Fore_color!=Back_color)
 | 
						|
    {
 | 
						|
      // 1er balayage (horizontal)
 | 
						|
      for (Pos_Y=1; Pos_Y<Brosse_Hauteur-1; Pos_Y++)
 | 
						|
      {
 | 
						|
        Etat=0;
 | 
						|
        for (Pos_X=1; Pos_X<Brosse_Largeur-1; Pos_X++)
 | 
						|
        {
 | 
						|
          if (Temporaire[((Pos_Y-1)*Largeur)+Pos_X-1]==Back_color)
 | 
						|
          {
 | 
						|
            if (Etat)
 | 
						|
            {
 | 
						|
              Pixel_dans_brosse(Pos_X,Pos_Y,Fore_color);
 | 
						|
              Etat=0;
 | 
						|
            }
 | 
						|
          }
 | 
						|
          else
 | 
						|
          {
 | 
						|
            if (!Etat)
 | 
						|
            {
 | 
						|
              Pixel_dans_brosse(Pos_X-1,Pos_Y,Fore_color);
 | 
						|
              Etat=1;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
        // Cas du dernier pixel à droite de la ligne
 | 
						|
        if (Etat)
 | 
						|
          Pixel_dans_brosse(Pos_X,Pos_Y,Fore_color);
 | 
						|
      }
 | 
						|
 | 
						|
      // 2ème balayage (vertical)
 | 
						|
      for (Pos_X=1; Pos_X<Brosse_Largeur-1; Pos_X++)
 | 
						|
      {
 | 
						|
        Etat=0;
 | 
						|
        for (Pos_Y=1; Pos_Y<Brosse_Hauteur-1; Pos_Y++)
 | 
						|
        {
 | 
						|
          if (Temporaire[((Pos_Y-1)*Largeur)+Pos_X-1]==Back_color)
 | 
						|
          {
 | 
						|
            if (Etat)
 | 
						|
            {
 | 
						|
              Pixel_dans_brosse(Pos_X,Pos_Y,Fore_color);
 | 
						|
              Etat=0;
 | 
						|
            }
 | 
						|
          }
 | 
						|
          else
 | 
						|
          {
 | 
						|
            if (!Etat)
 | 
						|
            {
 | 
						|
              Pixel_dans_brosse(Pos_X,Pos_Y-1,Fore_color);
 | 
						|
              Etat=1;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
        // Cas du dernier pixel en bas de la colonne
 | 
						|
        if (Etat)
 | 
						|
          Pixel_dans_brosse(Pos_X,Pos_Y,Fore_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 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_Y<Brosse_Hauteur; Pos_Y++)
 | 
						|
      {
 | 
						|
        Etat=(Temporaire[(Pos_Y+1)*Largeur]!=Back_color);
 | 
						|
        for (Pos_X=0; Pos_X<Brosse_Largeur; Pos_X++)
 | 
						|
        {
 | 
						|
          if (Temporaire[((Pos_Y+1)*Largeur)+Pos_X+1]==Back_color)
 | 
						|
          {
 | 
						|
            if (Etat)
 | 
						|
            {
 | 
						|
              if (Pos_X>0)
 | 
						|
                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_X<Brosse_Largeur; Pos_X++)
 | 
						|
      {
 | 
						|
        Etat=(Temporaire[Largeur+Pos_X+1]!=Back_color);;
 | 
						|
        for (Pos_Y=0; Pos_Y<Brosse_Hauteur; Pos_Y++)
 | 
						|
        {
 | 
						|
          if (Temporaire[((Pos_Y+1)*Largeur)+Pos_X+1]==Back_color)
 | 
						|
          {
 | 
						|
            if (Etat)
 | 
						|
            {
 | 
						|
              if (Pos_Y>0)
 | 
						|
                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 /////////////////////////////
 | 
						|
//////////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
 | 
						|
void Fill(short * Limite_atteinte_Haut  , short * Limite_atteinte_Bas,
 | 
						|
          short * Limite_atteinte_Gauche, short * Limite_atteinte_Droite)
 | 
						|
//
 | 
						|
//   Cette fonction fait un remplissage classique d'une zone délimitée de
 | 
						|
// l'image. Les limites employées sont Limite_Haut, Limite_Bas, Limite_Gauche
 | 
						|
// et Limite_Droite. Le point de départ du remplissage est Pinceau_X,Pinceau_Y
 | 
						|
// et s'effectue en théorie sur la couleur 1 et emploie la couleur 2 pour le
 | 
						|
// remplissage. Ces restrictions sont dûes à l'utilisation qu'on en fait dans
 | 
						|
// la fonction principale "Remplir", qui se charge de faire une gestion de
 | 
						|
// tous les effets.
 | 
						|
//   Cette fonction ne doit pas être directement appelée.
 | 
						|
//
 | 
						|
{
 | 
						|
  short Pos_X;   // Abscisse de balayage du segment, utilisée lors de l'"affichage"
 | 
						|
  short Ligne;   // Ordonnée de la ligne en cours de traitement
 | 
						|
  short Debut_X; // Abscisse de départ du segment traité
 | 
						|
  short Fin_X;   // Abscisse de fin du segment traité
 | 
						|
  int   Modifs_effectuees;    // Booléen "On a fait une modif dans le dernier passage"
 | 
						|
  int   Propagation_possible; // Booléen "On peut propager la couleur dans le segment"
 | 
						|
  short Limite_courante_Bas;  // Intervalle vertical restreint
 | 
						|
  short Limite_courante_Haut;
 | 
						|
  int   Ligne_modifiee;       // Booléen "On a fait une modif dans la ligne"
 | 
						|
 | 
						|
  Modifs_effectuees=1;
 | 
						|
  Limite_courante_Haut=Pinceau_Y;
 | 
						|
  Limite_courante_Bas =Min(Pinceau_Y+1,Limite_Bas);
 | 
						|
  *Limite_atteinte_Gauche=Pinceau_X;
 | 
						|
  *Limite_atteinte_Droite=Pinceau_X+1;
 | 
						|
  Pixel_dans_ecran_courant(Pinceau_X,Pinceau_Y,2);
 | 
						|
 | 
						|
  while (Modifs_effectuees)
 | 
						|
  {
 | 
						|
    Modifs_effectuees=0;
 | 
						|
 | 
						|
    for (Ligne=Limite_courante_Haut;Ligne<=Limite_courante_Bas;Ligne++)
 | 
						|
    {
 | 
						|
      Ligne_modifiee=0;
 | 
						|
      // On va traiter le cas de la ligne n° Ligne.
 | 
						|
 | 
						|
      // On commence le traitement à la gauche de l'écran
 | 
						|
      Debut_X=Limite_Gauche;
 | 
						|
 | 
						|
      // Pour chaque segment de couleur 1 que peut contenir la ligne
 | 
						|
      while (Debut_X<=Limite_Droite)
 | 
						|
      {
 | 
						|
        // On cherche son début
 | 
						|
        while((Debut_X<=Limite_Droite) && 
 | 
						|
                (Lit_pixel_dans_ecran_courant(Debut_X,Ligne)!=1))
 | 
						|
             Debut_X++;
 | 
						|
 | 
						|
        if (Debut_X<=Limite_Droite)
 | 
						|
        {
 | 
						|
          // Un segment de couleur 1 existe et commence à la position Debut_X.
 | 
						|
          // On va donc en chercher la fin.
 | 
						|
          for (Fin_X=Debut_X+1;(Fin_X<=Limite_Droite) &&
 | 
						|
               (Lit_pixel_dans_ecran_courant(Fin_X,Ligne)==1);Fin_X++);
 | 
						|
 | 
						|
          //   On sait qu'il existe un segment de couleur 1 qui commence en
 | 
						|
          // Debut_X et qui se termine en Fin_X-1.
 | 
						|
 | 
						|
          //   On va maintenant regarder si une couleur sur la périphérie
 | 
						|
          // permet de colorier ce segment avec la couleur 2.
 | 
						|
 | 
						|
          Propagation_possible=(
 | 
						|
            // Test de la présence d'un point à gauche du segment
 | 
						|
            ((Debut_X>Limite_Gauche) &&
 | 
						|
             (Lit_pixel_dans_ecran_courant(Debut_X-1,Ligne)==2)) ||
 | 
						|
            // Test de la présence d'un point à droite du segment
 | 
						|
            ((Fin_X-1<Limite_Droite) &&
 | 
						|
             (Lit_pixel_dans_ecran_courant(Fin_X    ,Ligne)==2))
 | 
						|
                               );
 | 
						|
 | 
						|
          // Test de la présence d'un point en haut du segment
 | 
						|
          if (!Propagation_possible && (Ligne>Limite_Haut))
 | 
						|
            for (Pos_X=Debut_X;Pos_X<Fin_X;Pos_X++)
 | 
						|
              if (Lit_pixel_dans_ecran_courant(Pos_X,Ligne-1)==2)
 | 
						|
              {
 | 
						|
                Propagation_possible=1;
 | 
						|
                break;
 | 
						|
              }
 | 
						|
 | 
						|
          if (Propagation_possible)
 | 
						|
          {
 | 
						|
            if (Debut_X<*Limite_atteinte_Gauche)
 | 
						|
              *Limite_atteinte_Gauche=Debut_X;
 | 
						|
            if (Fin_X>*Limite_atteinte_Droite)
 | 
						|
              *Limite_atteinte_Droite=Fin_X;
 | 
						|
            // On remplit le segment de Debut_X à Fin_X-1.
 | 
						|
            for (Pos_X=Debut_X;Pos_X<Fin_X;Pos_X++)
 | 
						|
              Pixel_dans_ecran_courant(Pos_X,Ligne,2);
 | 
						|
            // On vient d'effectuer des modifications.
 | 
						|
            Modifs_effectuees=1;
 | 
						|
            Ligne_modifiee=1;
 | 
						|
          }
 | 
						|
 | 
						|
          Debut_X=Fin_X+1;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      // Si on est en bas, et qu'on peut se propager vers le bas...
 | 
						|
      if ( (Ligne==Limite_courante_Bas) &&
 | 
						|
           (Ligne_modifiee) &&
 | 
						|
           (Limite_courante_Bas<Limite_Bas) )
 | 
						|
        Limite_courante_Bas++; // On descend cette limite vers le bas
 | 
						|
    }
 | 
						|
 | 
						|
    // Pour le prochain balayage vers le haut, on va se permettre d'aller
 | 
						|
    // voir une ligne plus haut.
 | 
						|
    // Si on ne le fait pas, et que la première ligne (Limite_courante_Haut)
 | 
						|
    // n'était pas modifiée, alors cette limite ne serait pas remontée, donc
 | 
						|
    // le filler ne progresserait pas vers le haut.
 | 
						|
    if (Limite_courante_Haut>Limite_Haut)
 | 
						|
      Limite_courante_Haut--;
 | 
						|
 | 
						|
    for (Ligne=Limite_courante_Bas;Ligne>=Limite_courante_Haut;Ligne--)
 | 
						|
    {
 | 
						|
      Ligne_modifiee=0;
 | 
						|
      // On va traiter le cas de la ligne n° Ligne.
 | 
						|
 | 
						|
      // On commence le traitement à la gauche de l'écran
 | 
						|
      Debut_X=Limite_Gauche;
 | 
						|
 | 
						|
      // Pour chaque segment de couleur 1 que peut contenir la ligne
 | 
						|
      while (Debut_X<=Limite_Droite)
 | 
						|
      {
 | 
						|
        // On cherche son début
 | 
						|
        for (;(Debut_X<=Limite_Droite) &&
 | 
						|
             (Lit_pixel_dans_ecran_courant(Debut_X,Ligne)!=1);Debut_X++);
 | 
						|
 | 
						|
        if (Debut_X<=Limite_Droite)
 | 
						|
        {
 | 
						|
          // Un segment de couleur 1 existe et commence à la position Debut_X.
 | 
						|
          // On va donc en chercher la fin.
 | 
						|
          for (Fin_X=Debut_X+1;(Fin_X<=Limite_Droite) &&
 | 
						|
               (Lit_pixel_dans_ecran_courant(Fin_X,Ligne)==1);Fin_X++);
 | 
						|
 | 
						|
          //   On sait qu'il existe un segment de couleur 1 qui commence en
 | 
						|
          // Debut_X et qui se termine en Fin_X-1.
 | 
						|
 | 
						|
          //   On va maintenant regarder si une couleur sur la périphérie
 | 
						|
          // permet de colorier ce segment avec la couleur 2.
 | 
						|
 | 
						|
          Propagation_possible=(
 | 
						|
            // Test de la présence d'un point à gauche du segment
 | 
						|
            ((Debut_X>Limite_Gauche) &&
 | 
						|
             (Lit_pixel_dans_ecran_courant(Debut_X-1,Ligne)==2)) ||
 | 
						|
            // Test de la présence d'un point à droite du segment
 | 
						|
            ((Fin_X-1<Limite_Droite) &&
 | 
						|
             (Lit_pixel_dans_ecran_courant(Fin_X    ,Ligne)==2))
 | 
						|
                               );
 | 
						|
 | 
						|
          // Test de la présence d'un point en bas du segment
 | 
						|
          if (!Propagation_possible && (Ligne<Limite_Bas))
 | 
						|
            for (Pos_X=Debut_X;Pos_X<Fin_X;Pos_X++)
 | 
						|
              if (Lit_pixel_dans_ecran_courant(Pos_X,Ligne+1)==2)
 | 
						|
              {
 | 
						|
                Propagation_possible=1;
 | 
						|
                break;
 | 
						|
              }
 | 
						|
 | 
						|
          if (Propagation_possible)
 | 
						|
          {
 | 
						|
            if (Debut_X<*Limite_atteinte_Gauche)
 | 
						|
              *Limite_atteinte_Gauche=Debut_X;
 | 
						|
            if (Fin_X>*Limite_atteinte_Droite)
 | 
						|
              *Limite_atteinte_Droite=Fin_X;
 | 
						|
            // On remplit le segment de Debut_X à Fin_X-1.
 | 
						|
            for (Pos_X=Debut_X;Pos_X<Fin_X;Pos_X++)
 | 
						|
              Pixel_dans_ecran_courant(Pos_X,Ligne,2);
 | 
						|
            // On vient d'effectuer des modifications.
 | 
						|
            Modifs_effectuees=1;
 | 
						|
            Ligne_modifiee=1;
 | 
						|
          }
 | 
						|
 | 
						|
          Debut_X=Fin_X+1;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      // Si on est en haut, et qu'on peut se propager vers le haut...
 | 
						|
      if ( (Ligne==Limite_courante_Haut) &&
 | 
						|
           (Ligne_modifiee) &&
 | 
						|
           (Limite_courante_Haut>Limite_Haut) )
 | 
						|
        Limite_courante_Haut--; // On monte cette limite vers le haut
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  *Limite_atteinte_Haut=Limite_courante_Haut;
 | 
						|
  *Limite_atteinte_Bas =Limite_courante_Bas;
 | 
						|
  (*Limite_atteinte_Droite)--;
 | 
						|
} // Fin de la routine de remplissage "Fill"
 | 
						|
 | 
						|
 | 
						|
void Remplir(byte Couleur_de_remplissage)
 | 
						|
//
 | 
						|
//  Cette fonction fait un remplissage qui gère tous les effets. Elle fait
 | 
						|
// appel à "Fill()".
 | 
						|
//
 | 
						|
{
 | 
						|
  byte   Forme_curseur_avant_remplissage;
 | 
						|
  byte * FX_Feedback_Ecran_avant_remplissage;
 | 
						|
  short  Pos_X,Pos_Y;
 | 
						|
  short  Limite_atteinte_Haut  ,Limite_atteinte_Bas;
 | 
						|
  short  Limite_atteinte_Gauche,Limite_atteinte_Droite;
 | 
						|
  byte   Table_de_remplacement[256];
 | 
						|
 | 
						|
 | 
						|
  // Avant toute chose, on vérifie que l'on n'est pas en train de remplir
 | 
						|
  // en dehors de l'image:
 | 
						|
 | 
						|
  if ( (Pinceau_X>=Limite_Gauche) &&
 | 
						|
       (Pinceau_X<=Limite_Droite) &&
 | 
						|
       (Pinceau_Y>=Limite_Haut)   &&
 | 
						|
       (Pinceau_Y<=Limite_Bas) )
 | 
						|
  {
 | 
						|
    // On suppose que le curseur est déjà caché.
 | 
						|
    // Effacer_curseur();
 | 
						|
 | 
						|
    //   On va faire patienter l'utilisateur en lui affichant un joli petit
 | 
						|
    // sablier:
 | 
						|
    Forme_curseur_avant_remplissage=Forme_curseur;
 | 
						|
    Forme_curseur=FORME_CURSEUR_SABLIER;
 | 
						|
    Afficher_curseur();
 | 
						|
 | 
						|
    // On commence par effectuer un backup de l'image.
 | 
						|
    Backup();
 | 
						|
 | 
						|
    // On fait attention au Feedback qui DOIT se faire avec le backup.
 | 
						|
    FX_Feedback_Ecran_avant_remplissage=FX_Feedback_Ecran;
 | 
						|
    FX_Feedback_Ecran=Ecran_backup;
 | 
						|
 | 
						|
    // On va maintenant "épurer" la zone visible de l'image:
 | 
						|
    memset(Table_de_remplacement,0,256);
 | 
						|
    Table_de_remplacement[Lit_pixel_dans_ecran_courant(Pinceau_X,Pinceau_Y)]=1;
 | 
						|
    Remplacer_toutes_les_couleurs_dans_limites(Table_de_remplacement);
 | 
						|
 | 
						|
    // On fait maintenant un remplissage classique de la couleur 1 avec la 2
 | 
						|
   Fill(&Limite_atteinte_Haut  ,&Limite_atteinte_Bas,
 | 
						|
         &Limite_atteinte_Gauche,&Limite_atteinte_Droite);
 | 
						|
 | 
						|
    //  On s'apprête à faire des opérations qui nécessitent un affichage. Il
 | 
						|
    // faut donc retirer de l'écran le curseur:
 | 
						|
    Effacer_curseur();
 | 
						|
    Forme_curseur=Forme_curseur_avant_remplissage;
 | 
						|
 | 
						|
    //  Il va maintenant falloir qu'on "turn" ce gros caca "into" un truc qui
 | 
						|
    // ressemble un peu plus à ce à quoi l'utilisateur peut s'attendre.
 | 
						|
    if (Limite_atteinte_Haut>Limite_Haut)
 | 
						|
      Copier_une_partie_d_image_dans_une_autre(Ecran_backup,					// Source
 | 
						|
                                               Limite_Gauche,Limite_Haut,			// Pos X et Y dans source
 | 
						|
                                               (Limite_Droite-Limite_Gauche)+1,			// Largeur copie
 | 
						|
                                               Limite_atteinte_Haut-Limite_Haut,		// Hauteur copie
 | 
						|
                                               Principal_Largeur_image,				// Largeur de la source
 | 
						|
					       Principal_Ecran,					// Destination
 | 
						|
                                               Limite_Gauche,Limite_Haut,			// Pos X et Y destination
 | 
						|
					       Principal_Largeur_image);			// Largeur destination
 | 
						|
    if (Limite_atteinte_Bas<Limite_Bas)
 | 
						|
      Copier_une_partie_d_image_dans_une_autre(Ecran_backup,
 | 
						|
                                               Limite_Gauche,Limite_atteinte_Bas+1,
 | 
						|
                                               (Limite_Droite-Limite_Gauche)+1,
 | 
						|
                                               Limite_Bas-Limite_atteinte_Bas,
 | 
						|
                                               Principal_Largeur_image,Principal_Ecran,
 | 
						|
                                               Limite_Gauche,Limite_atteinte_Bas+1,Principal_Largeur_image);
 | 
						|
    if (Limite_atteinte_Gauche>Limite_Gauche)
 | 
						|
      Copier_une_partie_d_image_dans_une_autre(Ecran_backup,
 | 
						|
                                               Limite_Gauche,Limite_atteinte_Haut,
 | 
						|
                                               Limite_atteinte_Gauche-Limite_Gauche,
 | 
						|
                                               (Limite_atteinte_Bas-Limite_atteinte_Haut)+1,
 | 
						|
                                               Principal_Largeur_image,Principal_Ecran,
 | 
						|
                                               Limite_Gauche,Limite_atteinte_Haut,Principal_Largeur_image);
 | 
						|
    if (Limite_atteinte_Droite<Limite_Droite)
 | 
						|
      Copier_une_partie_d_image_dans_une_autre(Ecran_backup,
 | 
						|
                                               Limite_atteinte_Droite+1,Limite_atteinte_Haut,
 | 
						|
                                               Limite_Droite-Limite_atteinte_Droite,
 | 
						|
                                               (Limite_atteinte_Bas-Limite_atteinte_Haut)+1,
 | 
						|
                                               Principal_Largeur_image,Principal_Ecran,
 | 
						|
                                               Limite_atteinte_Droite+1,Limite_atteinte_Haut,Principal_Largeur_image);
 | 
						|
 | 
						|
    for (Pos_Y=Limite_atteinte_Haut;Pos_Y<=Limite_atteinte_Bas;Pos_Y++)
 | 
						|
      for (Pos_X=Limite_atteinte_Gauche;Pos_X<=Limite_atteinte_Droite;Pos_X++)
 | 
						|
        if (Lit_pixel_dans_ecran_courant(Pos_X,Pos_Y)==2)
 | 
						|
        {
 | 
						|
          //   Si le pixel en cours de traitement a été touché par le Fill()
 | 
						|
          // on se doit d'afficher le pixel modifié par la couleur de
 | 
						|
          // remplissage:
 | 
						|
 | 
						|
          //  Ceci se fait en commençant par restaurer la couleur qu'il y avait
 | 
						|
          // précédemment (c'est important pour que les effets ne s'emmèlent
 | 
						|
          // pas le pinceaux)
 | 
						|
          Pixel_dans_ecran_courant(Pos_X,Pos_Y,Lit_pixel_dans_ecran_backup(Pos_X,Pos_Y));
 | 
						|
 | 
						|
          //  Enfin, on peut afficher le pixel, en le soumettant aux effets en
 | 
						|
          // cours:
 | 
						|
          Afficher_pixel(Pos_X,Pos_Y,Couleur_de_remplissage);
 | 
						|
        }
 | 
						|
        else
 | 
						|
          Pixel_dans_ecran_courant(Pos_X,Pos_Y,Lit_pixel_dans_ecran_backup(Pos_X,Pos_Y));
 | 
						|
 | 
						|
    FX_Feedback_Ecran=FX_Feedback_Ecran_avant_remplissage;
 | 
						|
 | 
						|
    //   A la fin, on n'a pas besoin de réafficher le curseur puisque c'est
 | 
						|
    // l'appelant qui s'en charge, et on n'a pas besoin de rafficher l'image
 | 
						|
    // puisque les seuls points qui ont changé dans l'image ont été raffichés
 | 
						|
    // par l'utilisation de "Afficher_pixel()", et que les autres... eh bein
 | 
						|
    // on n'y a jamais touché à l'écran les autres: ils sont donc corrects.
 | 
						|
 | 
						|
    UpdateRect(0,0,0,0);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
//////////////////////////////////////////////////////////////////////////////
 | 
						|
////////////////// TRACéS DE FIGURES GéOMéTRIQUES STANDARDS //////////////////
 | 
						|
////////////////////////// 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)
 | 
						|
  {
 | 
						|
    Afficher_pinceau(Pos_X,Pos_Y,Couleur,0);
 | 
						|
  }
 | 
						|
 | 
						|
  // Affichage d'un point pour une preview
 | 
						|
  void Pixel_figure_Preview(word Pos_X,word Pos_Y,byte Couleur)
 | 
						|
  {
 | 
						|
    if ( (Pos_X>=Limite_Gauche) &&
 | 
						|
         (Pos_X<=Limite_Droite) &&
 | 
						|
         (Pos_Y>=Limite_Haut)   &&
 | 
						|
         (Pos_Y<=Limite_Bas) )
 | 
						|
      Pixel_Preview(Pos_X,Pos_Y,Couleur);
 | 
						|
  }
 | 
						|
 | 
						|
  // Affichage d'un point pour une preview en xor
 | 
						|
  void Pixel_figure_Preview_xor(word Pos_X,word Pos_Y,__attribute__((unused)) byte Couleur)
 | 
						|
  {
 | 
						|
    if ( (Pos_X>=Limite_Gauche) &&
 | 
						|
         (Pos_X<=Limite_Droite) &&
 | 
						|
         (Pos_Y>=Limite_Haut)   &&
 | 
						|
         (Pos_Y<=Limite_Bas) )
 | 
						|
      Pixel_Preview(Pos_X,Pos_Y,~Lit_pixel(Pos_X-Principal_Decalage_X,
 | 
						|
                                           Pos_Y-Principal_Decalage_Y));
 | 
						|
  }
 | 
						|
 | 
						|
  // Effacement d'un point de preview
 | 
						|
  void Pixel_figure_Effacer_preview(word Pos_X,word Pos_Y,__attribute__((unused)) byte Couleur)
 | 
						|
  {
 | 
						|
    if ( (Pos_X>=Limite_Gauche) &&
 | 
						|
         (Pos_X<=Limite_Droite) &&
 | 
						|
         (Pos_Y>=Limite_Haut)   &&
 | 
						|
         (Pos_Y<=Limite_Bas) )
 | 
						|
      Pixel_Preview(Pos_X,Pos_Y,Lit_pixel_dans_ecran_courant(Pos_X,Pos_Y));
 | 
						|
  }
 | 
						|
 | 
						|
  // Affichage d'un point dans la brosse
 | 
						|
  void Pixel_figure_Dans_brosse(word Pos_X,word Pos_Y,byte Couleur)
 | 
						|
  {
 | 
						|
    Pos_X-=Brosse_Decalage_X;
 | 
						|
    Pos_Y-=Brosse_Decalage_Y;
 | 
						|
    if ( (Pos_X<Brosse_Largeur) && // Les pos sont des word donc jamais < 0 ...
 | 
						|
         (Pos_Y<Brosse_Hauteur) )
 | 
						|
      Pixel_dans_brosse(Pos_X,Pos_Y,Couleur);
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  // -- Tracer général d'un cercle vide -------------------------------------
 | 
						|
 | 
						|
void Tracer_cercle_vide_General(short Centre_X,short Centre_Y,short Rayon,byte Couleur)
 | 
						|
{
 | 
						|
  short Debut_X;
 | 
						|
  short Debut_Y;
 | 
						|
  short Pos_X;
 | 
						|
  short Pos_Y;
 | 
						|
 | 
						|
  // Ensuite, on va parcourire le quart haut gauche du cercle
 | 
						|
  Debut_X=Centre_X-Rayon;
 | 
						|
  Debut_Y=Centre_Y-Rayon;
 | 
						|
 | 
						|
  // Affichage des extremitées du cercle sur chaque quart du cercle:
 | 
						|
  for (Pos_Y=Debut_Y,Cercle_Curseur_Y=-Rayon;Pos_Y<Centre_Y;Pos_Y++,Cercle_Curseur_Y++)
 | 
						|
    for (Pos_X=Debut_X,Cercle_Curseur_X=-Rayon;Pos_X<Centre_X;Pos_X++,Cercle_Curseur_X++)
 | 
						|
      if (Pixel_dans_cercle())
 | 
						|
      {
 | 
						|
        // On vient de tomber sur le premier point sur la ligne horizontale
 | 
						|
        // qui fait partie du cercle.
 | 
						|
        // Donc on peut l'afficher (lui et ses copains symétriques)
 | 
						|
 | 
						|
         // Quart Haut-gauche
 | 
						|
        Pixel_figure(Pos_X,Pos_Y,Couleur);
 | 
						|
         // Quart Haut-droite
 | 
						|
        Pixel_figure((Centre_X<<1)-Pos_X,Pos_Y,Couleur);
 | 
						|
         // Quart Bas-droite
 | 
						|
        Pixel_figure((Centre_X<<1)-Pos_X,(Centre_Y<<1)-Pos_Y,Couleur);
 | 
						|
         // Quart Bas-gauche
 | 
						|
        Pixel_figure(Pos_X,(Centre_Y<<1)-Pos_Y,Couleur);
 | 
						|
 | 
						|
        // On peut ensuite afficher tous les points qui le suivent dont le
 | 
						|
        // pixel voisin du haut n'appartient pas au cercle:
 | 
						|
        for (Cercle_Curseur_Y--,Pos_X++,Cercle_Curseur_X++;Pos_X<Centre_X;Pos_X++,Cercle_Curseur_X++)
 | 
						|
          if (!Pixel_dans_cercle())
 | 
						|
          {
 | 
						|
             // Quart Haut-gauche
 | 
						|
            Pixel_figure(Pos_X,Pos_Y,Couleur);
 | 
						|
             // Quart Haut-droite
 | 
						|
            Pixel_figure((Centre_X<<1)-Pos_X,Pos_Y,Couleur);
 | 
						|
             // Quart Bas-gauche
 | 
						|
            Pixel_figure(Pos_X,(Centre_Y<<1)-Pos_Y,Couleur);
 | 
						|
             // Quart Bas-droite
 | 
						|
            Pixel_figure((Centre_X<<1)-Pos_X,(Centre_Y<<1)-Pos_Y,Couleur);
 | 
						|
          }
 | 
						|
          else
 | 
						|
            break;
 | 
						|
 | 
						|
        Cercle_Curseur_Y++;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
  // On affiche à la fin les points cardinaux:
 | 
						|
  Pixel_figure(Centre_X,Centre_Y-Rayon,Couleur); // Haut
 | 
						|
  Pixel_figure(Centre_X-Rayon,Centre_Y,Couleur); // Gauche
 | 
						|
  Pixel_figure(Centre_X+Rayon,Centre_Y,Couleur); // Droite
 | 
						|
  Pixel_figure(Centre_X,Centre_Y+Rayon,Couleur); // Bas
 | 
						|
 | 
						|
  if(Loupe_Mode) Mettre_Ecran_A_Jour(Centre_X-Rayon,Centre_Y-Rayon,2*Rayon+1,2*Rayon+1);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Tracé définitif d'un cercle vide --
 | 
						|
 | 
						|
void Tracer_cercle_vide_Definitif(short Centre_X,short Centre_Y,short Rayon,byte Couleur)
 | 
						|
{
 | 
						|
  Pixel_figure=Pixel_figure_Definitif;
 | 
						|
  Tracer_cercle_vide_General(Centre_X,Centre_Y,Rayon,Couleur);
 | 
						|
  Mettre_Ecran_A_Jour(Centre_X - Rayon, Centre_Y - Rayon, 2* Rayon+1, 2*Rayon+1);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Tracer la preview d'un cercle vide --
 | 
						|
 | 
						|
void Tracer_cercle_vide_Preview(short Centre_X,short Centre_Y,short Rayon,byte Couleur)
 | 
						|
{
 | 
						|
  Pixel_figure=Pixel_figure_Preview;
 | 
						|
  Tracer_cercle_vide_General(Centre_X,Centre_Y,Rayon,Couleur);
 | 
						|
  Mettre_Ecran_A_Jour(Centre_X - Rayon, Centre_Y - Rayon, 2* Rayon+1, 2*Rayon+1);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Effacer la preview d'un cercle vide --
 | 
						|
 | 
						|
void Effacer_cercle_vide_Preview(short Centre_X,short Centre_Y,short Rayon)
 | 
						|
{
 | 
						|
  Pixel_figure=Pixel_figure_Effacer_preview;
 | 
						|
  Tracer_cercle_vide_General(Centre_X,Centre_Y,Rayon,0);
 | 
						|
  Mettre_Ecran_A_Jour(Centre_X - Rayon, Centre_Y - Rayon, 2* Rayon+1, 2*Rayon+1);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Tracer un cercle plein --
 | 
						|
 | 
						|
void Tracer_cercle_plein(short Centre_X,short Centre_Y,short Rayon,byte Couleur)
 | 
						|
{
 | 
						|
  short Debut_X;
 | 
						|
  short Debut_Y;
 | 
						|
  short Pos_X;
 | 
						|
  short Pos_Y;
 | 
						|
  short Fin_X;
 | 
						|
  short Fin_Y;
 | 
						|
 | 
						|
  Debut_X=Centre_X-Rayon;
 | 
						|
  Debut_Y=Centre_Y-Rayon;
 | 
						|
  Fin_X=Centre_X+Rayon;
 | 
						|
  Fin_Y=Centre_Y+Rayon;
 | 
						|
 | 
						|
  // Correction des bornes d'après les limites
 | 
						|
  if (Debut_Y<Limite_Haut)
 | 
						|
    Debut_Y=Limite_Haut;
 | 
						|
  if (Fin_Y>Limite_Bas)
 | 
						|
    Fin_Y=Limite_Bas;
 | 
						|
  if (Debut_X<Limite_Gauche)
 | 
						|
    Debut_X=Limite_Gauche;
 | 
						|
  if (Fin_X>Limite_Droite)
 | 
						|
    Fin_X=Limite_Droite;
 | 
						|
 | 
						|
  // Affichage du cercle
 | 
						|
  for (Pos_Y=Debut_Y,Cercle_Curseur_Y=(long)Debut_Y-Centre_Y;Pos_Y<=Fin_Y;Pos_Y++,Cercle_Curseur_Y++)
 | 
						|
    for (Pos_X=Debut_X,Cercle_Curseur_X=(long)Debut_X-Centre_X;Pos_X<=Fin_X;Pos_X++,Cercle_Curseur_X++)
 | 
						|
      if (Pixel_dans_cercle())
 | 
						|
        Afficher_pixel(Pos_X,Pos_Y,Couleur);
 | 
						|
 | 
						|
  Mettre_Ecran_A_Jour(Debut_X,Debut_Y,Fin_X+1-Debut_X,Fin_Y+1-Debut_Y);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
  // -- Tracer général d'une ellipse vide -----------------------------------
 | 
						|
 | 
						|
void Tracer_ellipse_vide_General(short Centre_X,short Centre_Y,short Rayon_horizontal,short Rayon_vertical,byte Couleur)
 | 
						|
{
 | 
						|
  short Debut_X;
 | 
						|
  short Debut_Y;
 | 
						|
  short Pos_X;
 | 
						|
  short Pos_Y;
 | 
						|
 | 
						|
  Debut_X=Centre_X-Rayon_horizontal;
 | 
						|
  Debut_Y=Centre_Y-Rayon_vertical;
 | 
						|
 | 
						|
  // Calcul des limites de l'ellipse
 | 
						|
  Ellipse_Calculer_limites(Rayon_horizontal+1,Rayon_vertical+1);
 | 
						|
 | 
						|
  // Affichage des extremitées de l'ellipse sur chaque quart de l'ellipse:
 | 
						|
  for (Pos_Y=Debut_Y,Ellipse_Curseur_Y=-Rayon_vertical;Pos_Y<Centre_Y;Pos_Y++,Ellipse_Curseur_Y++)
 | 
						|
    for (Pos_X=Debut_X,Ellipse_Curseur_X=-Rayon_horizontal;Pos_X<Centre_X;Pos_X++,Ellipse_Curseur_X++)
 | 
						|
      if (Pixel_dans_ellipse())
 | 
						|
      {
 | 
						|
        // On vient de tomber sur le premier point qui sur la ligne
 | 
						|
        // horizontale fait partie de l'ellipse.
 | 
						|
 | 
						|
        // Donc on peut l'afficher (lui et ses copains symétriques)
 | 
						|
 | 
						|
         // Quart Haut-gauche
 | 
						|
        Pixel_figure(Pos_X,Pos_Y,Couleur);
 | 
						|
         // Quart Haut-droite
 | 
						|
        Pixel_figure((Centre_X<<1)-Pos_X,Pos_Y,Couleur);
 | 
						|
         // Quart Bas-gauche
 | 
						|
        Pixel_figure(Pos_X,(Centre_Y<<1)-Pos_Y,Couleur);
 | 
						|
         // Quart Bas-droite
 | 
						|
        Pixel_figure((Centre_X<<1)-Pos_X,(Centre_Y<<1)-Pos_Y,Couleur);
 | 
						|
 | 
						|
        // On peut ensuite afficher tous les points qui le suivent dont le
 | 
						|
        // pixel voisin du haut n'appartient pas à l'ellipse:
 | 
						|
        for (Ellipse_Curseur_Y--,Pos_X++,Ellipse_Curseur_X++;Pos_X<Centre_X;Pos_X++,Ellipse_Curseur_X++)
 | 
						|
          if (!Pixel_dans_ellipse())
 | 
						|
          {
 | 
						|
             // Quart Haut-gauche
 | 
						|
            Pixel_figure(Pos_X,Pos_Y,Couleur);
 | 
						|
             // Quart Haut-droite
 | 
						|
            Pixel_figure((Centre_X<<1)-Pos_X,Pos_Y,Couleur);
 | 
						|
             // Quart Bas-gauche
 | 
						|
            Pixel_figure(Pos_X,(Centre_Y<<1)-Pos_Y,Couleur);
 | 
						|
             // Quart Bas-droite
 | 
						|
            Pixel_figure((Centre_X<<1)-Pos_X,(Centre_Y<<1)-Pos_Y,Couleur);
 | 
						|
          }
 | 
						|
          else
 | 
						|
            break;
 | 
						|
 | 
						|
        Ellipse_Curseur_Y++;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
  // On affiche à la fin les points cardinaux:
 | 
						|
 | 
						|
  // Points verticaux:
 | 
						|
  Pos_X=Centre_X;
 | 
						|
  Ellipse_Curseur_X=-1;
 | 
						|
  for (Pos_Y=Centre_Y+1-Rayon_vertical,Ellipse_Curseur_Y=-Rayon_vertical+1;Pos_Y<Centre_Y+Rayon_vertical;Pos_Y++,Ellipse_Curseur_Y++)
 | 
						|
    if (!Pixel_dans_ellipse())
 | 
						|
      Pixel_figure(Pos_X,Pos_Y,Couleur);
 | 
						|
 | 
						|
  // Points horizontaux:
 | 
						|
  Pos_Y=Centre_Y;
 | 
						|
  Ellipse_Curseur_Y=-1;
 | 
						|
  for (Pos_X=Centre_X+1-Rayon_horizontal,Ellipse_Curseur_X=-Rayon_horizontal+1;Pos_X<Centre_X+Rayon_horizontal;Pos_X++,Ellipse_Curseur_X++)
 | 
						|
    if (!Pixel_dans_ellipse())
 | 
						|
      Pixel_figure(Pos_X,Pos_Y,Couleur);
 | 
						|
 | 
						|
  Pixel_figure(Centre_X,Centre_Y-Rayon_vertical,Couleur);   // Haut
 | 
						|
  Pixel_figure(Centre_X-Rayon_horizontal,Centre_Y,Couleur); // Gauche
 | 
						|
  Pixel_figure(Centre_X+Rayon_horizontal,Centre_Y,Couleur); // Droite
 | 
						|
  Pixel_figure(Centre_X,Centre_Y+Rayon_vertical,Couleur);   // Bas
 | 
						|
 | 
						|
  Mettre_Ecran_A_Jour(Centre_X-Rayon_horizontal,Centre_Y-Rayon_vertical,2*Rayon_horizontal+1,2*Rayon_vertical+1);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Tracé définitif d'une ellipse vide --
 | 
						|
 | 
						|
void Tracer_ellipse_vide_Definitif(short Centre_X,short Centre_Y,short Rayon_horizontal,short Rayon_vertical,byte Couleur)
 | 
						|
{
 | 
						|
  Pixel_figure=Pixel_figure_Definitif;
 | 
						|
  Tracer_ellipse_vide_General(Centre_X,Centre_Y,Rayon_horizontal,Rayon_vertical,Couleur);
 | 
						|
  Mettre_Ecran_A_Jour(Centre_X - Rayon_horizontal, Centre_Y - Rayon_vertical, 2* Rayon_horizontal+1, 2*Rayon_vertical+1);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Tracer la preview d'une ellipse vide --
 | 
						|
 | 
						|
void Tracer_ellipse_vide_Preview(short Centre_X,short Centre_Y,short Rayon_horizontal,short Rayon_vertical,byte Couleur)
 | 
						|
{
 | 
						|
  Pixel_figure=Pixel_figure_Preview;
 | 
						|
  Tracer_ellipse_vide_General(Centre_X,Centre_Y,Rayon_horizontal,Rayon_vertical,Couleur);
 | 
						|
  Mettre_Ecran_A_Jour(Centre_X - Rayon_horizontal, Centre_Y - Rayon_vertical, 2* Rayon_horizontal+1, 2*Rayon_vertical +1);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Effacer la preview d'une ellipse vide --
 | 
						|
 | 
						|
void Effacer_ellipse_vide_Preview(short Centre_X,short Centre_Y,short Rayon_horizontal,short Rayon_vertical)
 | 
						|
{
 | 
						|
  Pixel_figure=Pixel_figure_Effacer_preview;
 | 
						|
  Tracer_ellipse_vide_General(Centre_X,Centre_Y,Rayon_horizontal,Rayon_vertical,0);
 | 
						|
  Mettre_Ecran_A_Jour(Centre_X - Rayon_horizontal, Centre_Y - Rayon_vertical, 2* Rayon_horizontal+1, 2*Rayon_vertical+1);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Tracer une ellipse pleine --
 | 
						|
 | 
						|
void Tracer_ellipse_pleine(short Centre_X,short Centre_Y,short Rayon_horizontal,short Rayon_vertical,byte Couleur)
 | 
						|
{
 | 
						|
  short Debut_X;
 | 
						|
  short Debut_Y;
 | 
						|
  short Pos_X;
 | 
						|
  short Pos_Y;
 | 
						|
  short Fin_X;
 | 
						|
  short Fin_Y;
 | 
						|
 | 
						|
  Debut_X=Centre_X-Rayon_horizontal;
 | 
						|
  Debut_Y=Centre_Y-Rayon_vertical;
 | 
						|
  Fin_X=Centre_X+Rayon_horizontal;
 | 
						|
  Fin_Y=Centre_Y+Rayon_vertical;
 | 
						|
 | 
						|
  // Calcul des limites de l'ellipse
 | 
						|
  Ellipse_Calculer_limites(Rayon_horizontal+1,Rayon_vertical+1);
 | 
						|
 | 
						|
  // Correction des bornes d'après les limites
 | 
						|
  if (Debut_Y<Limite_Haut)
 | 
						|
    Debut_Y=Limite_Haut;
 | 
						|
  if (Fin_Y>Limite_Bas)
 | 
						|
    Fin_Y=Limite_Bas;
 | 
						|
  if (Debut_X<Limite_Gauche)
 | 
						|
    Debut_X=Limite_Gauche;
 | 
						|
  if (Fin_X>Limite_Droite)
 | 
						|
    Fin_X=Limite_Droite;
 | 
						|
 | 
						|
  // Affichage de l'ellipse
 | 
						|
  for (Pos_Y=Debut_Y,Ellipse_Curseur_Y=Debut_Y-Centre_Y;Pos_Y<=Fin_Y;Pos_Y++,Ellipse_Curseur_Y++)
 | 
						|
    for (Pos_X=Debut_X,Ellipse_Curseur_X=Debut_X-Centre_X;Pos_X<=Fin_X;Pos_X++,Ellipse_Curseur_X++)
 | 
						|
      if (Pixel_dans_ellipse())
 | 
						|
        Afficher_pixel(Pos_X,Pos_Y,Couleur);
 | 
						|
  Mettre_Ecran_A_Jour(Centre_X-Rayon_horizontal,Centre_Y-Rayon_vertical,2*Rayon_horizontal+1,2*Rayon_vertical+1);
 | 
						|
}
 | 
						|
 | 
						|
/******************
 | 
						|
* TRACÉ DE LIGNES *
 | 
						|
******************/
 | 
						|
 | 
						|
void Rectifier_coordonnees_a_45_degres(short AX, short AY, short* BX, short* BY)
 | 
						|
// Modifie BX et BY pour que la ligne AXAY - BXBY soit
 | 
						|
//	- une droite horizontale
 | 
						|
//	- une droite verticale
 | 
						|
//	- une droite avec une pente de 45 degrés
 | 
						|
{
 | 
						|
    int dx, dy;
 | 
						|
    float tan;
 | 
						|
 | 
						|
    dx = (*BX)-AX;
 | 
						|
    dy = AY- *BY; // On prend l'opposée car à l'écran les Y sont positifs en bas, et en maths, positifs en haut
 | 
						|
 | 
						|
    if (dx==0) return; // On est en lockx et de toutes façons le X n'a pas bougé, on sort tout de suite pour éviter une méchante division par 0
 | 
						|
 | 
						|
    tan = (float)dy/(float)dx;
 | 
						|
 | 
						|
    if (tan <= 0.4142 && tan >= -0.4142)
 | 
						|
    {
 | 
						|
	// Cas 1 : Lock Y
 | 
						|
	*BY = AY;
 | 
						|
    }
 | 
						|
    else if ( tan > 0.4142 && tan < 2.4142)
 | 
						|
    {
 | 
						|
	// Cas 2 : dy=dx
 | 
						|
	int nBY = AY - dx;
 | 
						|
	*BY = (*BY + nBY)/2;
 | 
						|
	*BX = AX  + AY - *BY;
 | 
						|
    }
 | 
						|
    else if (tan < -0.4142 && tan >= -2.4142)
 | 
						|
    {
 | 
						|
	// Cas 8 : dy = -dx
 | 
						|
	int nBY = AY + dx;
 | 
						|
	*BY = (*BY + nBY)/2;
 | 
						|
	*BX = AX  - AY + *BY;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	// Cas 3 : Lock X
 | 
						|
	*BX = AX;
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
  // -- Tracer général d'une ligne ------------------------------------------
 | 
						|
 | 
						|
void Tracer_ligne_General(short Debut_X,short Debut_Y,short Fin_X,short Fin_Y, byte Couleur)
 | 
						|
{
 | 
						|
  short Pos_X,Pos_Y;
 | 
						|
  short Incr_X,Incr_Y;
 | 
						|
  short i,Cumul;
 | 
						|
  short Delta_X,Delta_Y;
 | 
						|
 | 
						|
 | 
						|
  Pos_X=Debut_X;
 | 
						|
  Pos_Y=Debut_Y;
 | 
						|
 | 
						|
  if (Debut_X<Fin_X)
 | 
						|
  {
 | 
						|
    Incr_X=+1;
 | 
						|
    Delta_X=Fin_X-Debut_X;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    Incr_X=-1;
 | 
						|
    Delta_X=Debut_X-Fin_X;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Debut_Y<Fin_Y)
 | 
						|
  {
 | 
						|
    Incr_Y=+1;
 | 
						|
    Delta_Y=Fin_Y-Debut_Y;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    Incr_Y=-1;
 | 
						|
    Delta_Y=Debut_Y-Fin_Y;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Delta_Y>Delta_X)
 | 
						|
  {
 | 
						|
    Cumul=Delta_Y>>1;
 | 
						|
    for (i=1; i<Delta_Y; i++)
 | 
						|
    {
 | 
						|
      Pos_Y+=Incr_Y;
 | 
						|
      Cumul+=Delta_X;
 | 
						|
      if (Cumul>=Delta_Y)
 | 
						|
      {
 | 
						|
        Cumul-=Delta_Y;
 | 
						|
        Pos_X+=Incr_X;
 | 
						|
      }
 | 
						|
      Pixel_figure(Pos_X,Pos_Y,Couleur);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    Cumul=Delta_X>>1;
 | 
						|
    for (i=1; i<Delta_X; i++)
 | 
						|
    {
 | 
						|
      Pos_X+=Incr_X;
 | 
						|
      Cumul+=Delta_Y;
 | 
						|
      if (Cumul>=Delta_X)
 | 
						|
      {
 | 
						|
        Cumul-=Delta_X;
 | 
						|
        Pos_Y+=Incr_Y;
 | 
						|
      }
 | 
						|
      Pixel_figure(Pos_X,Pos_Y,Couleur);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if ( (Debut_X!=Fin_X) || (Debut_Y!=Fin_Y) )
 | 
						|
    Pixel_figure(Fin_X,Fin_Y,Couleur);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
  // -- Tracer définitif d'une ligne --
 | 
						|
 | 
						|
void Tracer_ligne_Definitif(short Debut_X,short Debut_Y,short Fin_X,short Fin_Y, byte Couleur)
 | 
						|
{
 | 
						|
 | 
						|
  int L = Fin_X-Debut_X, H = Fin_Y - Debut_Y;
 | 
						|
  Pixel_figure=Pixel_figure_Definitif;
 | 
						|
  Tracer_ligne_General(Debut_X,Debut_Y,Fin_X,Fin_Y,Couleur);
 | 
						|
  Mettre_Ecran_A_Jour((Debut_X<Fin_X)?Debut_X:Fin_X,(Debut_Y<Fin_Y)?Debut_Y:Fin_Y,abs(L)+1,abs(H)+1);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Tracer la preview d'une ligne --
 | 
						|
 | 
						|
void Tracer_ligne_Preview(short Debut_X,short Debut_Y,short Fin_X,short Fin_Y,byte Couleur)
 | 
						|
{
 | 
						|
  int L = Fin_X-Debut_X, H = Fin_Y - Debut_Y;
 | 
						|
  Pixel_figure=Pixel_figure_Preview;
 | 
						|
  Tracer_ligne_General(Debut_X,Debut_Y,Fin_X,Fin_Y,Couleur);
 | 
						|
  Mettre_Ecran_A_Jour((Debut_X<Fin_X)?Debut_X:Fin_X,(Debut_Y<Fin_Y)?Debut_Y:Fin_Y,abs(L)+1,abs(H)+1);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Tracer la preview d'une ligne en xor --
 | 
						|
 | 
						|
void Tracer_ligne_Preview_xor(short Debut_X,short Debut_Y,short Fin_X,short Fin_Y,byte Couleur)
 | 
						|
{
 | 
						|
  int L = Fin_X-Debut_X, H = Fin_Y - Debut_Y;
 | 
						|
  Pixel_figure=Pixel_figure_Preview_xor;
 | 
						|
  Tracer_ligne_General(Debut_X,Debut_Y,Fin_X,Fin_Y,Couleur);
 | 
						|
  Mettre_Ecran_A_Jour((Debut_X<Fin_X)?Debut_X:Fin_X,(Debut_Y<Fin_Y)?Debut_Y:Fin_Y,abs(L)+1,abs(H)+1);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Effacer la preview d'une ligne --
 | 
						|
 | 
						|
void Effacer_ligne_Preview(short Debut_X,short Debut_Y,short Fin_X,short Fin_Y)
 | 
						|
{
 | 
						|
  int L = Fin_X-Debut_X, H = Fin_Y - Debut_Y;
 | 
						|
  Pixel_figure=Pixel_figure_Effacer_preview;
 | 
						|
  Tracer_ligne_General(Debut_X,Debut_Y,Fin_X,Fin_Y,0);
 | 
						|
  Mettre_Ecran_A_Jour((Debut_X<Fin_X)?Debut_X:Fin_X,(Debut_Y<Fin_Y)?Debut_Y:Fin_Y,abs(L)+1,abs(H)+1);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
  // -- Tracer un rectangle vide --
 | 
						|
 | 
						|
void Tracer_rectangle_vide(short Debut_X,short Debut_Y,short Fin_X,short Fin_Y,byte Couleur)
 | 
						|
{
 | 
						|
  short Tempo;
 | 
						|
  short Pos_X;
 | 
						|
  short Pos_Y;
 | 
						|
 | 
						|
 | 
						|
  // On vérifie que les bornes soient dans le bon sens:
 | 
						|
  if (Debut_X>Fin_X)
 | 
						|
  {
 | 
						|
    Tempo=Debut_X;
 | 
						|
    Debut_X=Fin_X;
 | 
						|
    Fin_X=Tempo;
 | 
						|
  }
 | 
						|
  if (Debut_Y>Fin_Y)
 | 
						|
  {
 | 
						|
    Tempo=Debut_Y;
 | 
						|
    Debut_Y=Fin_Y;
 | 
						|
    Fin_Y=Tempo;
 | 
						|
  }
 | 
						|
 | 
						|
  // On trace le rectangle:
 | 
						|
 | 
						|
  for (Pos_X=Debut_X;Pos_X<=Fin_X;Pos_X++)
 | 
						|
    Afficher_pinceau(Pos_X,Debut_Y,Couleur,0);
 | 
						|
 | 
						|
  for (Pos_Y=Debut_Y+1;Pos_Y<Fin_Y;Pos_Y++)
 | 
						|
  {
 | 
						|
    Afficher_pinceau(Debut_X,Pos_Y,Couleur,0);
 | 
						|
    Afficher_pinceau(  Fin_X,Pos_Y,Couleur,0);
 | 
						|
  }
 | 
						|
 | 
						|
  for (Pos_X=Debut_X;Pos_X<=Fin_X;Pos_X++)
 | 
						|
    Afficher_pinceau(Pos_X,  Fin_Y,Couleur,0);
 | 
						|
#ifdef __macosx__
 | 
						|
  Mettre_Ecran_A_Jour(Debut_X,Fin_X,Fin_X-Debut_X,Fin_Y-Debut_Y);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
  // -- Tracer un rectangle plein --
 | 
						|
 | 
						|
void Tracer_rectangle_plein(short Debut_X,short Debut_Y,short Fin_X,short Fin_Y,byte Couleur)
 | 
						|
{
 | 
						|
  short Tempo;
 | 
						|
  short Pos_X;
 | 
						|
  short Pos_Y;
 | 
						|
 | 
						|
 | 
						|
  // On vérifie que les bornes sont dans le bon sens:
 | 
						|
  if (Debut_X>Fin_X)
 | 
						|
  {
 | 
						|
    Tempo=Debut_X;
 | 
						|
    Debut_X=Fin_X;
 | 
						|
    Fin_X=Tempo;
 | 
						|
  }
 | 
						|
  if (Debut_Y>Fin_Y)
 | 
						|
  {
 | 
						|
    Tempo=Debut_Y;
 | 
						|
    Debut_Y=Fin_Y;
 | 
						|
    Fin_Y=Tempo;
 | 
						|
  }
 | 
						|
 | 
						|
  // Correction en cas de dépassement des limites de l'image
 | 
						|
  if (Fin_X>Limite_Droite)
 | 
						|
    Fin_X=Limite_Droite;
 | 
						|
  if (Fin_Y>Limite_Bas)
 | 
						|
    Fin_Y=Limite_Bas;
 | 
						|
 | 
						|
  // On trace le rectangle:
 | 
						|
  for (Pos_Y=Debut_Y;Pos_Y<=Fin_Y;Pos_Y++)
 | 
						|
    for (Pos_X=Debut_X;Pos_X<=Fin_X;Pos_X++)
 | 
						|
      // Afficher_pixel traite chaque pixel avec tous les effets ! (smear, ...)
 | 
						|
      // Donc on ne peut pas otimiser en traçant ligne par ligne avec memset :(
 | 
						|
      Afficher_pixel(Pos_X,Pos_Y,Couleur);
 | 
						|
  Mettre_Ecran_A_Jour(Debut_X,Debut_Y,Fin_X-Debut_X,Fin_Y-Debut_Y);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
  // -- Tracer une courbe de Bézier --
 | 
						|
 | 
						|
void Tracer_courbe_General(short X1, short Y1,
 | 
						|
                           short X2, short Y2,
 | 
						|
                           short X3, short Y3,
 | 
						|
                           short X4, short Y4,
 | 
						|
                           byte Couleur)
 | 
						|
{
 | 
						|
  float Delta,T,T2,T3;
 | 
						|
  short X,Y,Old_X,Old_Y;
 | 
						|
  word  i;
 | 
						|
  int   CX[4];
 | 
						|
  int   CY[4];
 | 
						|
 | 
						|
  // Calcul des vecteurs de coefficients
 | 
						|
  CX[0]= -   X1 + 3*X2 - 3*X3 + X4;
 | 
						|
  CX[1]= + 3*X1 - 6*X2 + 3*X3;
 | 
						|
  CX[2]= - 3*X1 + 3*X2;
 | 
						|
  CX[3]= +   X1;
 | 
						|
  CY[0]= -   Y1 + 3*Y2 - 3*Y3 + Y4;
 | 
						|
  CY[1]= + 3*Y1 - 6*Y2 + 3*Y3;
 | 
						|
  CY[2]= - 3*Y1 + 3*Y2;
 | 
						|
  CY[3]= +   Y1;
 | 
						|
 | 
						|
  // Traçage de la courbe
 | 
						|
  Old_X=X1;
 | 
						|
  Old_Y=Y1;
 | 
						|
  Pixel_figure(Old_X,Old_Y,Couleur);
 | 
						|
  Delta=0.05; // 1.0/20
 | 
						|
  T=0;
 | 
						|
  for (i=1; i<=20; i++)
 | 
						|
  {
 | 
						|
    T=T+Delta; T2=T*T; T3=T2*T;
 | 
						|
    X=Round(T3*CX[0] + T2*CX[1] + T*CX[2] + CX[3]);
 | 
						|
    Y=Round(T3*CY[0] + T2*CY[1] + T*CY[2] + CY[3]);
 | 
						|
    Tracer_ligne_General(Old_X,Old_Y,X,Y,Couleur);
 | 
						|
    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;
 | 
						|
  Old_Y = Max(Max(Y1,Y2),Max(Y3,Y4)) - Y;
 | 
						|
  Mettre_Ecran_A_Jour(X,Y,Old_X,Old_Y); //A optimiser !! on update à chaque pixel affiché !
 | 
						|
}
 | 
						|
 | 
						|
  // -- Tracer une courbe de Bézier définitivement --
 | 
						|
 | 
						|
void Tracer_courbe_Definitif(short X1, short Y1,
 | 
						|
                             short X2, short Y2,
 | 
						|
                             short X3, short Y3,
 | 
						|
                             short X4, short Y4,
 | 
						|
                             byte Couleur)
 | 
						|
{
 | 
						|
  Pixel_figure=Pixel_figure_Definitif;
 | 
						|
  Tracer_courbe_General(X1,Y1,X2,Y2,X3,Y3,X4,Y4,Couleur);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Tracer la preview d'une courbe de Bézier --
 | 
						|
 | 
						|
void Tracer_courbe_Preview(short X1, short Y1,
 | 
						|
                           short X2, short Y2,
 | 
						|
                           short X3, short Y3,
 | 
						|
                           short X4, short Y4,
 | 
						|
                           byte Couleur)
 | 
						|
{
 | 
						|
  Pixel_figure=Pixel_figure_Preview;
 | 
						|
  Tracer_courbe_General(X1,Y1,X2,Y2,X3,Y3,X4,Y4,Couleur);
 | 
						|
}
 | 
						|
 | 
						|
  // -- Effacer la preview d'une courbe de Bézier --
 | 
						|
 | 
						|
void Effacer_courbe_Preview(short X1, short Y1,
 | 
						|
                            short X2, short Y2,
 | 
						|
                            short X3, short Y3,
 | 
						|
                            short X4, short Y4,
 | 
						|
                            byte Couleur)
 | 
						|
{
 | 
						|
  Pixel_figure=Pixel_figure_Effacer_preview;
 | 
						|
  Tracer_courbe_General(X1,Y1,X2,Y2,X3,Y3,X4,Y4,Couleur);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
  // -- Spray : un petit coup de Pschiitt! --
 | 
						|
 | 
						|
void Aerographe(short Bouton_clicke)
 | 
						|
{
 | 
						|
  short Pos_X,Pos_Y;
 | 
						|
  short Rayon=Spray_Size>>1;
 | 
						|
  long  Rayon_au_carre=(long)Rayon*Rayon;
 | 
						|
  short Indice,Count;
 | 
						|
  byte  Indice_couleur;
 | 
						|
  byte  Sens;
 | 
						|
 | 
						|
 | 
						|
  Effacer_curseur();
 | 
						|
 | 
						|
  if (Spray_Mode)
 | 
						|
  {
 | 
						|
    for (Count=1; Count<=Spray_Mono_flow; Count++)
 | 
						|
    {
 | 
						|
      Pos_X=(rand()%Spray_Size)-Rayon;
 | 
						|
      Pos_Y=(rand()%Spray_Size)-Rayon;
 | 
						|
      if ( (Pos_X*Pos_X)+(Pos_Y*Pos_Y) <= Rayon_au_carre )
 | 
						|
      {
 | 
						|
        Pos_X+=Pinceau_X;
 | 
						|
        Pos_Y+=Pinceau_Y;
 | 
						|
        if (Bouton_clicke==1)
 | 
						|
          Afficher_pinceau(Pos_X,Pos_Y,Fore_color,0);
 | 
						|
        else
 | 
						|
          Afficher_pinceau(Pos_X,Pos_Y,Back_color,0);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    //   On essaye de se balader dans la table des flux de façon à ce que ce
 | 
						|
    // ne soit pas toujours la dernière couleur qui soit affichée en dernier
 | 
						|
    // Pour ça, on part d'une couleur au pif dans une direction aléatoire.
 | 
						|
    Sens=rand()&1;
 | 
						|
    for (Indice=0,Indice_couleur=rand()/*%256*/; Indice<256; Indice++)
 | 
						|
    {
 | 
						|
      for (Count=1; Count<=Spray_Multi_flow[Indice_couleur]; Count++)
 | 
						|
      {
 | 
						|
        Pos_X=(rand()%Spray_Size)-Rayon;
 | 
						|
        Pos_Y=(rand()%Spray_Size)-Rayon;
 | 
						|
        if ( (Pos_X*Pos_X)+(Pos_Y*Pos_Y) <= Rayon_au_carre )
 | 
						|
        {
 | 
						|
          Pos_X+=Pinceau_X;
 | 
						|
          Pos_Y+=Pinceau_Y;
 | 
						|
          if (Bouton_clicke==A_GAUCHE)
 | 
						|
            Afficher_pinceau(Pos_X,Pos_Y,Indice_couleur,0);
 | 
						|
          else
 | 
						|
            Afficher_pinceau(Pos_X,Pos_Y,Back_color,0);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (Sens)
 | 
						|
        Indice_couleur++;
 | 
						|
      else
 | 
						|
        Indice_couleur--;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Afficher_curseur();
 | 
						|
 | 
						|
  for (Count=1; Count<=Spray_Delay; Count++)
 | 
						|
    Wait_VBL();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
  //////////////////////////////////////////////////////////////////////////
 | 
						|
  ////////////////////////// GESTION DES DEGRADES //////////////////////////
 | 
						|
  //////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
 | 
						|
  // -- Gestion d'un dégradé de base (le plus moche) --
 | 
						|
 | 
						|
void Degrade_de_base(long Indice,short Pos_X,short Pos_Y)
 | 
						|
{
 | 
						|
  long Position;
 | 
						|
 | 
						|
  // On fait un premier calcul partiel
 | 
						|
  Position=(Indice*Degrade_Intervalle_bornes);
 | 
						|
 | 
						|
  // On gère un déplacement au hasard
 | 
						|
  Position+=(Degrade_Intervalle_total*(rand()%Degrade_Melange_aleatoire)) >>6;
 | 
						|
  Position-=(Degrade_Intervalle_total*Degrade_Melange_aleatoire) >>7;
 | 
						|
 | 
						|
  Position/=Degrade_Intervalle_total;
 | 
						|
 | 
						|
  //   On va vérifier que nos petites idioties n'ont pas éjecté la valeur hors
 | 
						|
  // des valeurs autorisées par le dégradé défini par l'utilisateur.
 | 
						|
 | 
						|
  if (Position<0)
 | 
						|
    Position=0;
 | 
						|
  else if (Position>=Degrade_Intervalle_bornes)
 | 
						|
    Position=Degrade_Intervalle_bornes-1;
 | 
						|
 | 
						|
  // On ramène ensuite la position dans le dégradé vers un numéro de couleur
 | 
						|
  if (Degrade_Inverse)
 | 
						|
    Traiter_pixel_de_degrade(Pos_X,Pos_Y,Degrade_Borne_Superieure-Position);
 | 
						|
  else
 | 
						|
    Traiter_pixel_de_degrade(Pos_X,Pos_Y,Degrade_Borne_Inferieure+Position);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
  // -- Gestion d'un dégradé par trames simples --
 | 
						|
 | 
						|
void Degrade_de_trames_simples(long Indice,short Pos_X,short Pos_Y)
 | 
						|
{
 | 
						|
  long Position_dans_degrade;
 | 
						|
  long Position_dans_segment;
 | 
						|
 | 
						|
  //
 | 
						|
  //   But de l'opération: en plus de calculer la position de base (désignée
 | 
						|
  // dans cette procédure par "Position_dans_degrade", on calcule la position
 | 
						|
  // de l'indice dans le schéma suivant:
 | 
						|
  //
 | 
						|
  //         | Les indices qui traînent de ce côté du segment se voient subir
 | 
						|
  //         | une incrémentation conditionnelle à leur position dans l'écran.
 | 
						|
  //         v
 | 
						|
  //  |---|---|---|---- - - -
 | 
						|
  //   ^
 | 
						|
  //   |_ Les indices qui traînent de ce côté du segment se voient subir une
 | 
						|
  //      décrémentation conditionnelle à leur position dans l'écran.
 | 
						|
 | 
						|
  // On fait d'abord un premier calcul partiel
 | 
						|
  Position_dans_degrade=(Indice*Degrade_Intervalle_bornes);
 | 
						|
 | 
						|
  // On gère un déplacement au hasard...
 | 
						|
  Position_dans_degrade+=(Degrade_Intervalle_total*(rand()%Degrade_Melange_aleatoire)) >>6;
 | 
						|
  Position_dans_degrade-=(Degrade_Intervalle_total*Degrade_Melange_aleatoire) >>7;
 | 
						|
 | 
						|
  if (Position_dans_degrade<0)
 | 
						|
    Position_dans_degrade=0;
 | 
						|
 | 
						|
  // ... qui nous permet de calculer la position dans le segment
 | 
						|
  Position_dans_segment=((Position_dans_degrade<<2)/Degrade_Intervalle_total)&3;
 | 
						|
 | 
						|
  // On peut ensuite terminer le calcul de l'indice dans le dégradé
 | 
						|
  Position_dans_degrade/=Degrade_Intervalle_total;
 | 
						|
 | 
						|
  // On va pouvoir discuter de la valeur de Position_dans_degrade en fonction
 | 
						|
  // de la position dans l'écran et de la Position_dans_segment.
 | 
						|
 | 
						|
  switch (Position_dans_segment)
 | 
						|
  {
 | 
						|
    case 0 : // On est sur la gauche du segment
 | 
						|
      if (((Pos_X+Pos_Y)&1)==0)
 | 
						|
        Position_dans_degrade--;
 | 
						|
      break;
 | 
						|
 | 
						|
      // On n'a pas à traiter les cas 1 et 2 car ils représentent des valeurs
 | 
						|
      // suffisament au centre du segment pour ne pas avoir à subir la trame
 | 
						|
 | 
						|
    case 3 : // On est sur la droite du segment
 | 
						|
      if (((Pos_X+Pos_Y)&1)!=0) // Note: on doit faire le test inverse au cas gauche pour synchroniser les 2 côtés de la trame.
 | 
						|
        Position_dans_degrade++;
 | 
						|
  }
 | 
						|
 | 
						|
  //   On va vérifier que nos petites idioties n'ont pas éjecté la valeur hors
 | 
						|
  // des valeurs autorisées par le dégradé défini par l'utilisateur.
 | 
						|
 | 
						|
  if (Position_dans_degrade<0)
 | 
						|
    Position_dans_degrade=0;
 | 
						|
  else if (Position_dans_degrade>=Degrade_Intervalle_bornes)
 | 
						|
    Position_dans_degrade=Degrade_Intervalle_bornes-1;
 | 
						|
 | 
						|
  // On ramène ensuite la position dans le dégradé vers un numéro de couleur
 | 
						|
  if (Degrade_Inverse)
 | 
						|
    Position_dans_degrade=Degrade_Borne_Superieure-Position_dans_degrade;
 | 
						|
  else
 | 
						|
    Position_dans_degrade=Degrade_Borne_Inferieure+Position_dans_degrade;
 | 
						|
 | 
						|
  Traiter_pixel_de_degrade(Pos_X,Pos_Y,Position_dans_degrade);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
  // -- Gestion d'un dégradé par trames étendues --
 | 
						|
 | 
						|
void Degrade_de_trames_etendues(long Indice,short Pos_X,short Pos_Y)
 | 
						|
{
 | 
						|
  long Position_dans_degrade;
 | 
						|
  long Position_dans_segment;
 | 
						|
 | 
						|
//
 | 
						|
  //   But de l'opération: en plus de calculer la position de base (désignée
 | 
						|
  // dans cette procédure par "Position_dans_degrade", on calcule la position
 | 
						|
  // de l'indice dans le schéma suivant:
 | 
						|
  //
 | 
						|
  //         | Les indices qui traînent de ce côté du segment se voient subir
 | 
						|
  //         | une incrémentation conditionnelle à leur position dans l'écran.
 | 
						|
  //         v
 | 
						|
  //  |---|---|---|---- - - -
 | 
						|
  //   ^
 | 
						|
  //   |_ Les indices qui traînent de ce côté du segment se voient subir une
 | 
						|
  //      décrémentation conditionnelle à leur position dans l'écran.
 | 
						|
 | 
						|
  // On fait d'abord un premier calcul partiel
 | 
						|
  Position_dans_degrade=(Indice*Degrade_Intervalle_bornes);
 | 
						|
 | 
						|
  // On gère un déplacement au hasard
 | 
						|
  Position_dans_degrade+=(Degrade_Intervalle_total*(rand()%Degrade_Melange_aleatoire)) >>6;
 | 
						|
  Position_dans_degrade-=(Degrade_Intervalle_total*Degrade_Melange_aleatoire) >>7;
 | 
						|
 | 
						|
  if (Position_dans_degrade<0)
 | 
						|
    Position_dans_degrade=0;
 | 
						|
 | 
						|
  // Qui nous permet de calculer la position dans le segment
 | 
						|
  Position_dans_segment=((Position_dans_degrade<<3)/Degrade_Intervalle_total)&7;
 | 
						|
 | 
						|
  // On peut ensuite terminer le calcul de l'indice dans le dégradé
 | 
						|
  Position_dans_degrade/=Degrade_Intervalle_total;
 | 
						|
 | 
						|
  // On va pouvoir discuter de la valeur de Position_dans_degrade en fonction
 | 
						|
  // de la position dans l'écran et de la Position_dans_segment.
 | 
						|
 | 
						|
  switch (Position_dans_segment)
 | 
						|
  {
 | 
						|
    case 0 : // On est sur l'extrême gauche du segment
 | 
						|
      if (((Pos_X+Pos_Y)&1)==0)
 | 
						|
        Position_dans_degrade--;
 | 
						|
      break;
 | 
						|
 | 
						|
    case 1 : // On est sur la gauche du segment
 | 
						|
    case 2 : // On est sur la gauche du segment
 | 
						|
      if (((Pos_X & 1)==0) && ((Pos_Y & 1)==0))
 | 
						|
        Position_dans_degrade--;
 | 
						|
      break;
 | 
						|
 | 
						|
      // On n'a pas à traiter les cas 3 et 4 car ils représentent des valeurs
 | 
						|
      // suffisament au centre du segment pour ne pas avoir à subir la trame
 | 
						|
 | 
						|
    case 5 : // On est sur la droite du segment
 | 
						|
    case 6 : // On est sur la droite du segment
 | 
						|
      if (((Pos_X & 1)==0) && ((Pos_Y & 1)!=0))
 | 
						|
        Position_dans_degrade++;
 | 
						|
      break;
 | 
						|
 | 
						|
    case 7 : // On est sur l'extreme droite du segment
 | 
						|
      if (((Pos_X+Pos_Y)&1)!=0) // Note: on doit faire le test inverse au cas gauche pour synchroniser les 2 côtés de la trame.
 | 
						|
        Position_dans_degrade++;
 | 
						|
  }
 | 
						|
 | 
						|
  //   On va vérifier que nos petites idioties n'ont pas éjecté la valeur hors
 | 
						|
  // des valeurs autorisées par le dégradé défini par l'utilisateur.
 | 
						|
 | 
						|
  if (Position_dans_degrade<0)
 | 
						|
    Position_dans_degrade=0;
 | 
						|
  else if (Position_dans_degrade>=Degrade_Intervalle_bornes)
 | 
						|
    Position_dans_degrade=Degrade_Intervalle_bornes-1;
 | 
						|
 | 
						|
  // On ramène ensuite la position dans le dégradé vers un numéro de couleur
 | 
						|
  if (Degrade_Inverse)
 | 
						|
    Position_dans_degrade=Degrade_Borne_Superieure-Position_dans_degrade;
 | 
						|
  else
 | 
						|
    Position_dans_degrade=Degrade_Borne_Inferieure+Position_dans_degrade;
 | 
						|
 | 
						|
  Traiter_pixel_de_degrade(Pos_X,Pos_Y,Position_dans_degrade);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
  // -- 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)
 | 
						|
{
 | 
						|
  long Debut_X;
 | 
						|
  long Debut_Y;
 | 
						|
  long Pos_X;
 | 
						|
  long Pos_Y;
 | 
						|
  long Fin_X;
 | 
						|
  long Fin_Y;
 | 
						|
  long Distance_X; // Distance (au carré) sur les X du point en cours au centre d'éclairage
 | 
						|
  long Distance_Y; // Distance (au carré) sur les Y du point en cours au centre d'éclairage
 | 
						|
 | 
						|
  Debut_X=Centre_X-Rayon;
 | 
						|
  Debut_Y=Centre_Y-Rayon;
 | 
						|
  Fin_X=Centre_X+Rayon;
 | 
						|
  Fin_Y=Centre_Y+Rayon;
 | 
						|
 | 
						|
  // Correction des bornes d'après les limites
 | 
						|
  if (Debut_Y<Limite_Haut)
 | 
						|
    Debut_Y=Limite_Haut;
 | 
						|
  if (Fin_Y>Limite_Bas)
 | 
						|
    Fin_Y=Limite_Bas;
 | 
						|
  if (Debut_X<Limite_Gauche)
 | 
						|
    Debut_X=Limite_Gauche;
 | 
						|
  if (Fin_X>Limite_Droite)
 | 
						|
    Fin_X=Limite_Droite;
 | 
						|
 | 
						|
  Degrade_Intervalle_total=Cercle_Limite+
 | 
						|
                           ((Centre_X-Eclairage_X)*(Centre_X-Eclairage_X))+
 | 
						|
                           ((Centre_Y-Eclairage_Y)*(Centre_Y-Eclairage_Y))+
 | 
						|
                           (2L*Rayon*sqrt(
 | 
						|
                           ((Centre_X-Eclairage_X)*(Centre_X-Eclairage_X))+
 | 
						|
                           ((Centre_Y-Eclairage_Y)*(Centre_Y-Eclairage_Y))));
 | 
						|
 | 
						|
  if (Degrade_Intervalle_total==0)
 | 
						|
    Degrade_Intervalle_total=1;
 | 
						|
 | 
						|
  // Affichage du cercle
 | 
						|
  for (Pos_Y=Debut_Y,Cercle_Curseur_Y=(long)Debut_Y-Centre_Y;Pos_Y<=Fin_Y;Pos_Y++,Cercle_Curseur_Y++)
 | 
						|
  {
 | 
						|
    Distance_Y =(Pos_Y-Eclairage_Y);
 | 
						|
    Distance_Y*=Distance_Y;
 | 
						|
    for (Pos_X=Debut_X,Cercle_Curseur_X=(long)Debut_X-Centre_X;Pos_X<=Fin_X;Pos_X++,Cercle_Curseur_X++)
 | 
						|
      if (Pixel_dans_cercle())
 | 
						|
      {
 | 
						|
        Distance_X =(Pos_X-Eclairage_X);
 | 
						|
        Distance_X*=Distance_X;
 | 
						|
        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);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
  // -- Tracer une ellipse degradée --
 | 
						|
 | 
						|
void Tracer_ellipse_degradee(short Centre_X,short Centre_Y,short Rayon_horizontal,short Rayon_vertical,short Eclairage_X,short Eclairage_Y)
 | 
						|
{
 | 
						|
  long Debut_X;
 | 
						|
  long Debut_Y;
 | 
						|
  long Pos_X;
 | 
						|
  long Pos_Y;
 | 
						|
  long Fin_X;
 | 
						|
  long Fin_Y;
 | 
						|
  long Distance_X; // Distance (au carré) sur les X du point en cours au centre d'éclairage
 | 
						|
  long Distance_Y; // Distance (au carré) sur les Y du point en cours au centre d'éclairage
 | 
						|
 | 
						|
 | 
						|
  Debut_X=Centre_X-Rayon_horizontal;
 | 
						|
  Debut_Y=Centre_Y-Rayon_vertical;
 | 
						|
  Fin_X=Centre_X+Rayon_horizontal;
 | 
						|
  Fin_Y=Centre_Y+Rayon_vertical;
 | 
						|
 | 
						|
  // Calcul des limites de l'ellipse
 | 
						|
  Ellipse_Calculer_limites(Rayon_horizontal+1,Rayon_vertical+1);
 | 
						|
 | 
						|
  // On calcule la distance maximale:
 | 
						|
  Degrade_Intervalle_total=(Rayon_horizontal*Rayon_horizontal)+
 | 
						|
                           (Rayon_vertical*Rayon_vertical)+
 | 
						|
                           ((Centre_X-Eclairage_X)*(Centre_X-Eclairage_X))+
 | 
						|
                           ((Centre_Y-Eclairage_Y)*(Centre_Y-Eclairage_Y))+
 | 
						|
                           (2L
 | 
						|
                           *sqrt(
 | 
						|
                           (Rayon_horizontal*Rayon_horizontal)+
 | 
						|
                           (Rayon_vertical  *Rayon_vertical  ))
 | 
						|
                           *sqrt(
 | 
						|
                           ((Centre_X-Eclairage_X)*(Centre_X-Eclairage_X))+
 | 
						|
                           ((Centre_Y-Eclairage_Y)*(Centre_Y-Eclairage_Y))));
 | 
						|
 | 
						|
  if (Degrade_Intervalle_total==0)
 | 
						|
    Degrade_Intervalle_total=1;
 | 
						|
 | 
						|
  // Correction des bornes d'après les limites
 | 
						|
  if (Debut_Y<Limite_Haut)
 | 
						|
    Debut_Y=Limite_Haut;
 | 
						|
  if (Fin_Y>Limite_Bas)
 | 
						|
    Fin_Y=Limite_Bas;
 | 
						|
  if (Debut_X<Limite_Gauche)
 | 
						|
    Debut_X=Limite_Gauche;
 | 
						|
  if (Fin_X>Limite_Droite)
 | 
						|
    Fin_X=Limite_Droite;
 | 
						|
 | 
						|
  // Affichage de l'ellipse
 | 
						|
  for (Pos_Y=Debut_Y,Ellipse_Curseur_Y=Debut_Y-Centre_Y;Pos_Y<=Fin_Y;Pos_Y++,Ellipse_Curseur_Y++)
 | 
						|
  {
 | 
						|
    Distance_Y =(Pos_Y-Eclairage_Y);
 | 
						|
    Distance_Y*=Distance_Y;
 | 
						|
    for (Pos_X=Debut_X,Ellipse_Curseur_X=Debut_X-Centre_X;Pos_X<=Fin_X;Pos_X++,Ellipse_Curseur_X++)
 | 
						|
      if (Pixel_dans_ellipse())
 | 
						|
      {
 | 
						|
        Distance_X =(Pos_X-Eclairage_X);
 | 
						|
        Distance_X*=Distance_X;
 | 
						|
        Traiter_degrade(Distance_X+Distance_Y,Pos_X,Pos_Y);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  Mettre_Ecran_A_Jour(Debut_X,Debut_Y,Fin_X-Debut_X+1,Fin_Y-Debut_Y+1);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Tracé d'un rectangle (RAX RAY - RBX RBY) dégradé selon le vecteur (VAX VAY - VBX - VBY)
 | 
						|
void Tracer_rectangle_degrade(short RAX,short RAY,short RBX,short RBY,short VAX,short VAY, short VBX, short VBY)
 | 
						|
{
 | 
						|
    short Pos_Y, Pos_X;
 | 
						|
 | 
						|
    // On commence par s'assurer que le rectangle est à l'endroit
 | 
						|
    if(RBX < RAX)
 | 
						|
    {
 | 
						|
	Pos_X = RBX;
 | 
						|
	RBX = RAX;
 | 
						|
	RAX = Pos_X;
 | 
						|
    }
 | 
						|
 | 
						|
    if(RBY < RAY)
 | 
						|
    {
 | 
						|
	Pos_Y = RBY;
 | 
						|
	RBY = RAY;
 | 
						|
	RAY = Pos_Y;
 | 
						|
    }
 | 
						|
 | 
						|
    if(VBX == VAX)
 | 
						|
    {
 | 
						|
	// Le vecteur est vertical, donc on évite la partie en dessous qui foirerait avec une division par 0...
 | 
						|
	if (VBY == VAY) return;	// L'utilisateur fait n'importe quoi
 | 
						|
	Degrade_Intervalle_total = abs(VBY - VAY);
 | 
						|
	for(Pos_Y=RAY;Pos_Y<=RBY;Pos_Y++)
 | 
						|
	    for(Pos_X=RAX;Pos_X<=RBX;Pos_X++)
 | 
						|
		Traiter_degrade(abs(VBY - Pos_Y),Pos_X,Pos_Y);
 | 
						|
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	short a,b;
 | 
						|
	int Distance_X, Distance_Y;
 | 
						|
 | 
						|
	Degrade_Intervalle_total = sqrt(pow(VBY - VAY,2)+pow(VBX - VAX,2));
 | 
						|
	a = (VBY - VAY)/(VBX - VAX);
 | 
						|
	b = VAY - a*VAX;
 | 
						|
 | 
						|
	for (Pos_Y=RAY;Pos_Y<=RBY;Pos_Y++)
 | 
						|
	    for (Pos_X = RAX;Pos_X<=RBX;Pos_X++)
 | 
						|
	    {
 | 
						|
		// On calcule ou on en est dans le dégradé
 | 
						|
		Distance_X = pow((int)(Pos_Y - VAY),2)+pow((int)(Pos_X - VAX),2);
 | 
						|
		Distance_Y = pow((int)(-a * Pos_X + Pos_Y - b),2)/(a*a+1);
 | 
						|
 | 
						|
		Traiter_degrade(sqrt(Distance_X - Distance_Y),Pos_X,Pos_Y);
 | 
						|
	    }
 | 
						|
    }
 | 
						|
    Mettre_Ecran_A_Jour(RAX,RAY,RBX,RBY);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// -- Tracer un polygône plein --
 | 
						|
 | 
						|
typedef struct POLYGON_EDGE      /* an active edge */
 | 
						|
{
 | 
						|
    short top;                     /* top y position */
 | 
						|
    short bottom;                  /* bottom y position */
 | 
						|
    float x, dx;                   /* floating point x position and gradient */
 | 
						|
    float w;                       /* width of line segment */
 | 
						|
    struct POLYGON_EDGE *prev;     /* doubly linked list */
 | 
						|
    struct POLYGON_EDGE *next;
 | 
						|
} POLYGON_EDGE;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* fill_edge_structure:
 | 
						|
 *  Polygon helper function: initialises an edge structure for the 2d
 | 
						|
 *  rasteriser.
 | 
						|
 */
 | 
						|
void fill_edge_structure(POLYGON_EDGE *edge, short *i1, short *i2)
 | 
						|
{
 | 
						|
  short *it;
 | 
						|
 | 
						|
  if (i2[1] < i1[1])
 | 
						|
  {
 | 
						|
    it = i1;
 | 
						|
    i1 = i2;
 | 
						|
    i2 = it;
 | 
						|
  }
 | 
						|
 | 
						|
  edge->top = i1[1];
 | 
						|
  edge->bottom = i2[1] - 1;
 | 
						|
  edge->dx = ((float) i2[0] - (float) i1[0]) / ((float) i2[1] - (float) i1[1]);
 | 
						|
  edge->x = i1[0] + 0.4999999;
 | 
						|
  edge->prev = NULL;
 | 
						|
  edge->next = NULL;
 | 
						|
 | 
						|
  if (edge->dx+1 < 0.0)
 | 
						|
    edge->x += edge->dx+1;
 | 
						|
 | 
						|
  if (edge->dx >= 0.0)
 | 
						|
    edge->w = edge->dx;
 | 
						|
  else
 | 
						|
    edge->w = -(edge->dx);
 | 
						|
 | 
						|
  if (edge->w-1.0<0.0)
 | 
						|
    edge->w = 0.0;
 | 
						|
  else
 | 
						|
    edge->w = edge->w-1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* add_edge:
 | 
						|
 *  Adds an edge structure to a linked list, returning the new head pointer.
 | 
						|
 */
 | 
						|
POLYGON_EDGE * add_edge(POLYGON_EDGE *list, POLYGON_EDGE *edge, int sort_by_x)
 | 
						|
{
 | 
						|
  POLYGON_EDGE *pos = list;
 | 
						|
  POLYGON_EDGE *prev = NULL;
 | 
						|
 | 
						|
  if (sort_by_x)
 | 
						|
  {
 | 
						|
    while ( (pos) && ((pos->x+((pos->w+pos->dx)/2)) < (edge->x+((edge->w+edge->dx)/2))) )
 | 
						|
    {
 | 
						|
      prev = pos;
 | 
						|
      pos = pos->next;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    while ((pos) && (pos->top < edge->top))
 | 
						|
    {
 | 
						|
      prev = pos;
 | 
						|
      pos = pos->next;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  edge->next = pos;
 | 
						|
  edge->prev = prev;
 | 
						|
 | 
						|
  if (pos)
 | 
						|
    pos->prev = edge;
 | 
						|
 | 
						|
  if (prev)
 | 
						|
  {
 | 
						|
    prev->next = edge;
 | 
						|
    return list;
 | 
						|
  }
 | 
						|
  else
 | 
						|
    return edge;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* remove_edge:
 | 
						|
 *  Removes an edge structure from a list, returning the new head pointer.
 | 
						|
 */
 | 
						|
POLYGON_EDGE * remove_edge(POLYGON_EDGE *list, POLYGON_EDGE *edge)
 | 
						|
{
 | 
						|
  if (edge->next)
 | 
						|
    edge->next->prev = edge->prev;
 | 
						|
 | 
						|
  if (edge->prev)
 | 
						|
  {
 | 
						|
    edge->prev->next = edge->next;
 | 
						|
    return list;
 | 
						|
  }
 | 
						|
  else
 | 
						|
    return edge->next;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* polygon:
 | 
						|
 *  Draws a filled polygon with an arbitrary number of corners. Pass the
 | 
						|
 *  number of vertices, then an array containing a series of x, y points
 | 
						|
 *  (a total of vertices*2 values).
 | 
						|
 */
 | 
						|
void Polyfill_General(int Vertices, short * Points, int Color)
 | 
						|
{
 | 
						|
  short c;
 | 
						|
  short top = 0x7FFF;
 | 
						|
  short bottom = 0;
 | 
						|
  short *i1, *i2;
 | 
						|
  short Pos_X,Fin_X;
 | 
						|
  POLYGON_EDGE *edge, *next_edge, *initial_edge;
 | 
						|
  POLYGON_EDGE *active_edges = NULL;
 | 
						|
  POLYGON_EDGE *inactive_edges = NULL;
 | 
						|
 | 
						|
 | 
						|
  /* allocate some space and fill the edge table */
 | 
						|
  initial_edge=edge=(POLYGON_EDGE *) malloc(sizeof(POLYGON_EDGE) * Vertices);
 | 
						|
 | 
						|
  i1 = Points;
 | 
						|
  i2 = Points + ((Vertices-1)<<1);
 | 
						|
 | 
						|
  for (c=0; c<Vertices; c++)
 | 
						|
  {
 | 
						|
    if (i1[1] != i2[1])
 | 
						|
    {
 | 
						|
      fill_edge_structure(edge, i1, i2);
 | 
						|
 | 
						|
      if (edge->bottom >= edge->top)
 | 
						|
      {
 | 
						|
        if (edge->top < top)
 | 
						|
          top = edge->top;
 | 
						|
 | 
						|
        if (edge->bottom > bottom)
 | 
						|
          bottom = edge->bottom;
 | 
						|
 | 
						|
        inactive_edges = add_edge(inactive_edges, edge, 0);
 | 
						|
        edge++;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    i2 = i1;
 | 
						|
    i1 += 2;
 | 
						|
  }
 | 
						|
 | 
						|
  /* for each scanline in the polygon... */
 | 
						|
  for (c=top; c<=bottom; c++)
 | 
						|
  {
 | 
						|
    /* check for newly active edges */
 | 
						|
    edge = inactive_edges;
 | 
						|
    while ((edge) && (edge->top == c))
 | 
						|
    {
 | 
						|
      next_edge = edge->next;
 | 
						|
      inactive_edges = remove_edge(inactive_edges, edge);
 | 
						|
      active_edges = add_edge(active_edges, edge, 1);
 | 
						|
      edge = next_edge;
 | 
						|
    }
 | 
						|
 | 
						|
    /* draw horizontal line segments */
 | 
						|
    if ((c>=Limite_Haut) && (c<=Limite_Bas))
 | 
						|
    {
 | 
						|
      edge = active_edges;
 | 
						|
      while ((edge) && (edge->next))
 | 
						|
      {
 | 
						|
        Pos_X=/*Round*/(edge->x);
 | 
						|
        Fin_X=/*Round*/(edge->next->x+edge->next->w);
 | 
						|
        if (Pos_X<Limite_Gauche)
 | 
						|
          Pos_X=Limite_Gauche;
 | 
						|
        if (Fin_X>Limite_Droite)
 | 
						|
          Fin_X=Limite_Droite;
 | 
						|
        for (; Pos_X<=Fin_X; Pos_X++)
 | 
						|
          Pixel_figure(Pos_X,c,Color);
 | 
						|
        edge = edge->next->next;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    /* update edges, sorting and removing dead ones */
 | 
						|
    edge = active_edges;
 | 
						|
    while (edge)
 | 
						|
    {
 | 
						|
      next_edge = edge->next;
 | 
						|
      if (c >= edge->bottom)
 | 
						|
        active_edges = remove_edge(active_edges, edge);
 | 
						|
      else
 | 
						|
      {
 | 
						|
        edge->x += edge->dx;
 | 
						|
        while ((edge->prev) && ( (edge->x+(edge->w/2)) < (edge->prev->x+(edge->prev->w/2))) )
 | 
						|
        {
 | 
						|
          if (edge->next)
 | 
						|
            edge->next->prev = edge->prev;
 | 
						|
          edge->prev->next = edge->next;
 | 
						|
          edge->next = edge->prev;
 | 
						|
          edge->prev = edge->prev->prev;
 | 
						|
          edge->next->prev = edge;
 | 
						|
          if (edge->prev)
 | 
						|
            edge->prev->next = edge;
 | 
						|
          else
 | 
						|
            active_edges = edge;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      edge = next_edge;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  free(initial_edge);
 | 
						|
  // On ne connait pas simplement les xmin et xmax ici, mais de toutes façon ce n'est pas utilisé en preview
 | 
						|
  Mettre_Ecran_A_Jour(0,top,Principal_Largeur_image,bottom-top+1);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void Polyfill(int Vertices, short * Points, int Color)
 | 
						|
{
 | 
						|
  Pixel_figure=Afficher_pixel;
 | 
						|
  Polyfill_General(Vertices,Points,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; Temporaire<Vertices; Temporaire++)
 | 
						|
  {
 | 
						|
    Pos_X=Points[Temporaire<<1];
 | 
						|
    Pos_Y=Points[(Temporaire<<1)+1];
 | 
						|
    if (Pos_X<Debut_X)
 | 
						|
      Debut_X=Pos_X;
 | 
						|
    if (Pos_X>Fin_X)
 | 
						|
      Fin_X=Pos_X;
 | 
						|
    if (Pos_Y<Debut_Y)
 | 
						|
      Debut_Y=Pos_Y;
 | 
						|
    if (Pos_Y>Fin_Y)
 | 
						|
      Fin_Y=Pos_Y;
 | 
						|
  }
 | 
						|
 | 
						|
  // On clippe ces bornes à l'écran:
 | 
						|
  if (Debut_X<Limite_Gauche)
 | 
						|
    Debut_X=Limite_Gauche;
 | 
						|
  if (Fin_X>Limite_Droite)
 | 
						|
    Fin_X=Limite_Droite;
 | 
						|
  if (Debut_Y<Limite_Haut)
 | 
						|
    Debut_Y=Limite_Haut;
 | 
						|
  if (Fin_Y>Limite_Bas)
 | 
						|
    Fin_Y=Limite_Bas;
 | 
						|
 | 
						|
  // On ne capture la nouvelle brosse que si elle est au moins partiellement
 | 
						|
  // dans l'image:
 | 
						|
 | 
						|
  if ((Debut_X<Principal_Largeur_image) && (Debut_Y<Principal_Hauteur_image))
 | 
						|
  {
 | 
						|
    // On met les décalages du tiling à 0 pour eviter toute incohérence.
 | 
						|
    // Si par hasard on voulait les mettre à
 | 
						|
    //    min(Tiling_Decalage_?,Brosse_?a??eur-1)
 | 
						|
    // il faudrait penser à les initialiser à 0 dans "MAIN.C".
 | 
						|
    Tiling_Decalage_X=0;
 | 
						|
    Tiling_Decalage_Y=0;
 | 
						|
 | 
						|
    // Ensuite, on calcule les dimensions de la brosse:
 | 
						|
    Nouvelle_Brosse_Largeur=(Fin_X-Debut_X)+1;
 | 
						|
    Nouvelle_Brosse_Hauteur=(Fin_Y-Debut_Y)+1;
 | 
						|
 | 
						|
    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;
 | 
						|
    }
 | 
						|
 | 
						|
    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<Vertices; Temporaire++)
 | 
						|
    {
 | 
						|
      Tracer_ligne_General(Points[(Temporaire-1)<<1],Points[((Temporaire-1)<<1)+1],
 | 
						|
                           Points[Temporaire<<1],Points[(Temporaire<<1)+1],
 | 
						|
                           ~Back_color);
 | 
						|
    }
 | 
						|
    Tracer_ligne_General(Points[(Vertices-1)<<1],Points[((Vertices-1)<<1)+1],
 | 
						|
                         Points[0],Points[1],
 | 
						|
                         ~Back_color);
 | 
						|
 | 
						|
    // On scanne la brosse pour remplacer tous les pixels affectés par le
 | 
						|
    // polyfill par ceux de l'image:
 | 
						|
    for (Pos_Y=Debut_Y;Pos_Y<=Fin_Y;Pos_Y++)
 | 
						|
      for (Pos_X=Debut_X;Pos_X<=Fin_X;Pos_X++)
 | 
						|
        if (Lit_pixel_dans_brosse(Pos_X-Debut_X,Pos_Y-Debut_Y)!=Back_color)
 | 
						|
        {
 | 
						|
          Pixel_dans_brosse(Pos_X-Debut_X,Pos_Y-Debut_Y,Lit_pixel_dans_ecran_courant(Pos_X,Pos_Y));
 | 
						|
          // On regarde s'il faut effacer quelque chose:
 | 
						|
          if (Effacement)
 | 
						|
            Pixel_dans_ecran_courant(Pos_X,Pos_Y,Back_color);
 | 
						|
        }
 | 
						|
 | 
						|
    // On centre la prise sur la brosse
 | 
						|
    Brosse_Decalage_X=(Brosse_Largeur>>1);
 | 
						|
    Brosse_Decalage_Y=(Brosse_Hauteur>>1);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
//------------ Remplacement de la couleur pointée par une autre --------------
 | 
						|
 | 
						|
void Remplacer(byte Nouvelle_couleur)
 | 
						|
{
 | 
						|
  byte Ancienne_couleur;
 | 
						|
 | 
						|
  if ((Pinceau_X<Principal_Largeur_image)
 | 
						|
   && (Pinceau_Y<Principal_Hauteur_image))
 | 
						|
  {
 | 
						|
    Ancienne_couleur=Lit_pixel_dans_ecran_courant(Pinceau_X,Pinceau_Y);
 | 
						|
    if ( (Ancienne_couleur!=Nouvelle_couleur)
 | 
						|
      && ((!Stencil_Mode) || (!Stencil[Ancienne_couleur])) )
 | 
						|
    {
 | 
						|
      Remplacer_une_couleur(Ancienne_couleur,Nouvelle_couleur);
 | 
						|
      Afficher_ecran();
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//------------------------- 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<X2)?1:-1;
 | 
						|
  Dy=(Y1<Y2)?1:-1;
 | 
						|
 | 
						|
  // Calcul des nouvelles dimensions de la brosse:
 | 
						|
  if ((New_Brosse_Largeur=X1-X2)<0)
 | 
						|
    New_Brosse_Largeur=-New_Brosse_Largeur;
 | 
						|
  New_Brosse_Largeur++;
 | 
						|
 | 
						|
  if ((New_Brosse_Hauteur=Y1-Y2)<0)
 | 
						|
    New_Brosse_Hauteur=-New_Brosse_Hauteur;
 | 
						|
  New_Brosse_Hauteur++;
 | 
						|
 | 
						|
  // Calcul des anciennes dimensions de la brosse:
 | 
						|
 | 
						|
  // Calcul du "vecteur incrémental":
 | 
						|
  Delta_X_dans_brosse=(Brosse_Largeur<<16)/(X2-X1+Dx);
 | 
						|
  Delta_Y_dans_brosse=(Brosse_Hauteur<<16)/(Y2-Y1+Dy);
 | 
						|
 | 
						|
  // Calcul de la valeur initiale de Pos_X pour chaque ligne:
 | 
						|
  if (Dx>=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<New_Brosse_Hauteur;Ligne++)
 | 
						|
    {
 | 
						|
      // On repart du début de la ligne:
 | 
						|
      Pos_X_dans_brosse=Pos_X_initial;
 | 
						|
 | 
						|
      // Pour chaque colonne:
 | 
						|
      for (Colonne=0;Colonne<New_Brosse_Largeur;Colonne++)
 | 
						|
      {
 | 
						|
        // On copie le pixel:
 | 
						|
        New_Brosse[Offset]=Lit_pixel_dans_brosse(Pos_X_dans_brosse>>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_X<Fin_X)
 | 
						|
  {
 | 
						|
    Incr_X=+1;
 | 
						|
    Delta_X=Delta_X2;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    Incr_X=-1;
 | 
						|
    Delta_X=-Delta_X2;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Debut_Y<Fin_Y)
 | 
						|
  {
 | 
						|
    Incr_Y=+1;
 | 
						|
    Delta_Y=Delta_Y2;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    Incr_Y=-1;
 | 
						|
    Delta_Y=-Delta_Y2;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Delta_X>Delta_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<Hauteur))
 | 
						|
      {
 | 
						|
        Xt=(((float)((Pos_X-Debut_X)*Delta_Xt))/(float)Delta_X2) + (float)Xt1;
 | 
						|
        Yt=(((float)((Pos_X-Debut_X)*Delta_Yt))/(float)Delta_X2) + (float)Yt1;
 | 
						|
        if (ScanY_X[0][Pos_Y]==INDEFINI) // Gauche non défini
 | 
						|
        {
 | 
						|
          ScanY_X[0][Pos_Y]=Pos_X;
 | 
						|
          ScanY_Xt[0][Pos_Y]=Xt;
 | 
						|
          ScanY_Yt[0][Pos_Y]=Yt;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          if (Pos_X>=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<Hauteur))
 | 
						|
      {
 | 
						|
        Xt=(((float)((Pos_Y-Debut_Y)*Delta_Xt))/(float)Delta_Y2) + (float)Xt1;
 | 
						|
        Yt=(((float)((Pos_Y-Debut_Y)*Delta_Yt))/(float)Delta_Y2) + (float)Yt1;
 | 
						|
        if (ScanY_X[0][Pos_Y]==INDEFINI) // Gauche non défini
 | 
						|
        {
 | 
						|
          ScanY_X[0][Pos_Y]=Pos_X;
 | 
						|
          ScanY_Xt[0][Pos_Y]=Xt;
 | 
						|
          ScanY_Yt[0][Pos_Y]=Yt;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          if (Pos_X>=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<Hauteur; Y++)
 | 
						|
  {
 | 
						|
    ScanY_X[0][Y]=INDEFINI;
 | 
						|
    ScanY_X[1][Y]=INDEFINI;
 | 
						|
  }
 | 
						|
 | 
						|
  Interpoler_texture(X1-Xmin,Y1-Ymin,Xt1,Yt1,X3-Xmin,Y3-Ymin,Xt3,Yt3,Hauteur);
 | 
						|
  Interpoler_texture(X3-Xmin,Y3-Ymin,Xt3,Yt3,X4-Xmin,Y4-Ymin,Xt4,Yt4,Hauteur);
 | 
						|
  Interpoler_texture(X4-Xmin,Y4-Ymin,Xt4,Yt4,X2-Xmin,Y2-Ymin,Xt2,Yt2,Hauteur);
 | 
						|
  Interpoler_texture(X2-Xmin,Y2-Ymin,Xt2,Yt2,X1-Xmin,Y1-Ymin,Xt1,Yt1,Hauteur);
 | 
						|
 | 
						|
  for (Y=0; Y<Hauteur; Y++)
 | 
						|
  {
 | 
						|
    Debut_X=Round(ScanY_X[0][Y]);
 | 
						|
    Fin_X  =Round(ScanY_X[1][Y]);
 | 
						|
 | 
						|
    Largeur_ligne=1+Fin_X-Debut_X;
 | 
						|
 | 
						|
    for (X=0; X<Debut_X; X++)
 | 
						|
      Buffer[X+(Y*Largeur)]=Back_color;
 | 
						|
    for (; X<=Fin_X; X++)
 | 
						|
    {
 | 
						|
      Temp=(float)(0.5+(float)X-ScanY_X[0][Y])/(float)Largeur_ligne;
 | 
						|
      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])));
 | 
						|
 | 
						|
      Buffer[X+(Y*Largeur)]=Lit_pixel_dans_brosse(Xt,Yt);
 | 
						|
    }
 | 
						|
    for (; X<Largeur; X++)
 | 
						|
      Buffer[X+(Y*Largeur)]=Back_color;
 | 
						|
  }
 | 
						|
 | 
						|
  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(float Angle)
 | 
						|
{
 | 
						|
  byte * New_Brosse;
 | 
						|
  int    New_Brosse_Largeur;  // Largeur de la nouvelle brosse
 | 
						|
  int    New_Brosse_Hauteur;  // Hauteur de la nouvelle brosse
 | 
						|
 | 
						|
  short X1,Y1,X2,Y2,X3,Y3,X4,Y4;
 | 
						|
  int Debut_X,Fin_X,Debut_Y,Fin_Y;
 | 
						|
  int Xmin,Xmax,Ymin,Ymax;
 | 
						|
  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);
 | 
						|
 | 
						|
  // 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; Y<Hauteur; Y++)
 | 
						|
  {
 | 
						|
    ScanY_X[0][Y]=INDEFINI;
 | 
						|
    ScanY_X[1][Y]=INDEFINI;
 | 
						|
  }
 | 
						|
 | 
						|
  Interpoler_texture(X1,Y1-Ymin,Xt1,Yt1,X3,Y3-Ymin,Xt3,Yt3,Hauteur);
 | 
						|
  Interpoler_texture(X3,Y3-Ymin,Xt3,Yt3,X4,Y4-Ymin,Xt4,Yt4,Hauteur);
 | 
						|
  Interpoler_texture(X4,Y4-Ymin,Xt4,Yt4,X2,Y2-Ymin,Xt2,Yt2,Hauteur);
 | 
						|
  Interpoler_texture(X2,Y2-Ymin,Xt2,Yt2,X1,Y1-Ymin,Xt1,Yt1,Hauteur);
 | 
						|
 | 
						|
  Ymin_=Ymin;
 | 
						|
  if (Ymin<Limite_Haut) Ymin=Limite_Haut;
 | 
						|
  if (Ymax>Limite_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_X<Limite_Gauche) Debut_X=Limite_Gauche;
 | 
						|
    if (  Fin_X>Limite_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);
 | 
						|
}
 |