1769 lines
57 KiB
C
1769 lines
57 KiB
C
/* Grafx2 - The Ultimate 256-color bitmap paint program
|
|
|
|
Copyright 2008 Franck Charlet
|
|
Copyright 2007-2008 Adrien Destugues
|
|
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
|
|
|
|
Grafx2 is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; version 2
|
|
of the License.
|
|
|
|
Grafx2 is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Grafx2; if not, see <http://www.gnu.org/licenses/> or
|
|
write to the Free Software Foundation, Inc.,
|
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
********************************************************************************
|
|
|
|
Brush manipulation functions
|
|
*/
|
|
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include <string.h> // memset()
|
|
|
|
#include "global.h"
|
|
#include "graph.h"
|
|
#include "divers.h"
|
|
#include "erreurs.h"
|
|
#include "windows.h"
|
|
#include "sdlscreen.h"
|
|
|
|
// Calcul de redimensionnement du pinceau pour éviter les débordements de
|
|
// l'écran et de l'image
|
|
void Calculer_dimensions_clipees(short * X,short * Y,short * Largeur,short * Hauteur)
|
|
{
|
|
if ((*X)<Limite_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,Largeur,Hauteur);
|
|
|
|
}
|
|
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);
|
|
|
|
}
|
|
}
|
|
|
|
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
|
|
{
|
|
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,Largeur,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);
|
|
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 ( (Pinceau_Sprite[(TAILLE_MAXI_PINCEAU*Compteur_Y)+Compteur_X]) // Le pinceau sert de masque pour dire quels pixels on doit traiter dans le rectangle
|
|
&& (Compteur_Y<Smear_Max_Y) && (Compteur_X<Smear_Max_X) // On clippe l'effet smear entre Smear_Min et Smear_Max
|
|
&& (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
|
|
{
|
|
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(Debut_X,Debut_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;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
}
|
|
Mettre_Ecran_A_Jour(Debut_X,Debut_Y,Brosse_Largeur,Brosse_Hauteur);
|
|
}
|
|
|
|
// 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 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!
|
|
}
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//------------------------- 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;
|
|
}
|
|
Mettre_Ecran_A_Jour(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);
|
|
Debut_X=Min(Min(X1,X2),Min(X3,X4));
|
|
Fin_X=Max(Max(X1,X2),Max(X3,X4));
|
|
Debut_Y=Min(Min(Y1,Y2),Min(Y3,Y4));
|
|
Fin_Y=Max(Max(Y1,Y2),Max(Y3,Y4));
|
|
Mettre_Ecran_A_Jour(Debut_X,Debut_Y,Fin_X-Debut_X+1,Fin_Y-Debut_Y+1);
|
|
}
|