Pour les sources, voir ez-draw.h, ez-draw.c.
Initialisation générale.
Renvoie 0 succès, -1 échec.
Boucle principale.
Cette fonction affiche les fenêtres créées, puis attend les évènements et appelle au fur et à mesure la fonction d’évènements correspondante (callback) de la fenêtre concernée.
Pour interrompre la boucle principale, appeler ez_quit() dans une callback. Une fois revenu de ez_main_loop(), il ne faut plus faire aucun graphisme.
Fait sortir de ez_main_loop().
Modifie l’effet du bouton “Fermer” de la barre de titre d’une fenêtre, pour toutes les fenêtres du programme.
Par défaut (cas où val = 1), si on clique sur le bouton “Fermer” de n’importe quelle fenêtre d’un programme, il se termine immédiatement.
Vous pouvez changer ce comportement en invoquant ez_auto_quit() avec val = 0 : si ensuite l’utilisateur clique sur le bouton “Fermer” d’une fenêtre, le programme (au lieu de se terminer) recevra l’évènement WindowClose pour cette fenêtre ; libre alors à votre programme de décider ce qu’il veut faire :
- ignorer l’évènement ;
- détruire la fenêtre avec ez_window_destroy() ;
- masquer la fenêtre avec ez_window_show() ;
- créer une fenêtre de dialogue ;
- terminer le programme avec ez_quit() ;
- etc.
Remarque : lorsque toutes les fenêtres sont détruites, le programme s’arrête.
Chaque fenêtre a un identifiant unique, de type Ez_window :
Identifiant d’une fenêtre, de type entier.
Les fonctions suivantes permettent de créer ou manipuler des fenêtres :
Crée et affiche une fenêtre, de largeur w et hauteur h, avec un titre name, et une fonction func appelée pour chaque évènement.
Renvoie l’identifiant entier de la fenêtre, de type Ez_window.
Rend visible (val = 1) ou cache (val = 0) la fenêtre win.
Chaque couleur est désignée par un entier de type Ez_uint32.
Mémorise la couleur color pour les prochains dessins, ainsi que pour l’affichage de texte.
Les couleurs suivantes sont prédéfinies : ez_black, ez_white, ez_grey, ez_red, ez_green, ez_blue, ez_yellow, ez_cyan, ez_magenta.
On peut fabriquer d’autres couleurs avec les fonctions suivantes :
Renvoie une couleur calculée à partir des niveaux r,g,b donnés entre 0 et 255.
Renvoie une couleur grise calculée à partir de son niveau g donné entre 0 et 255.
Renvoie une couleur calculée dans l’espace Hue, Saturation, Value.
h est un angle entre 0 et 360 degrés qui représente arbitrairement les couleurs pures ; s est la saturation, entre 0 et 1 ; v est la valeur de luminosité, entre 0 et 1. Pour en savoir plus, consulter l’article Teinte Saturation Valeur dans Wikipedia.
Convertit une couleur de l’espace HSV en RGB.
Les intervalles sont : h entre 0 et 360, s et v entre 0 et 1, *r, *g, *b entre 0 et 255.
Comme exemples, voir demo-11.c et demo-12.c.
On obtient ces fenêtres :
Les coordonnées sont relatives à l’origine, qui est le point en haut à gauche de l’intérieur de la fenêtre ; x va vers la droite et y va vers le bas.
Pour les rectangles et les cercles, x1,y1 et y2,y2 sont les coordonnées en haut à gauche et en bas à droite de la boîte englobante. Pour les points, les segments de droite et les triangles, on passe les coordonnées des sommets.
Par défaut, la couleur est le noir ; elle se change avec ez_set_color().
Dessine un triangle.
Dessine un triangle plein.
Les dessins réalisés avec ez_draw_point(), ez_draw_line(), ez_draw_rectangle(), ez_draw_triangle(), ez_draw_circle() ont une épaisseur par défaut de 1 pixel. On peut modifier l’épaisseur avec :
Mémorise l’épaisseur thick (en pixels) pour les prochains dessins.
Charge une fonte à partir de son nom (par exemple "6x13") et la stocke pour le numéro num.
Renvoie 0 succès, -1 erreur.
Le numéro de fonte doit être inférieur à EZ_FONT_MAX. Quelques fontes fixes sont préchargées par défaut :
- Fonte numéro 0 : "6x13"
- Fonte numéro 1 : "8x16"
- Fonte numéro 2 : "10x20"
- Fonte numéro 3 : "12x24"
Mémorise le numéro de fonte num pour les prochains affichages de texte.
Affiche du texte ; s’utilise comme printf.
Exemple :
ez_draw_text (win, EZ_TL, 10, 10, "Largeur = %d\nHauteur = %d", w, h);
Les coordonnées x1,y1 sont données par rapport à align, qui prend pour valeurs :
EZ_TL (Top Left) | EZ_TC (Top Center) | EZ_TR (Top Right) |
EZ_ML (Middle Left) | EZ_MC (Middle Center) | EZ_MR (Middle Right) |
EZ_BL (Bottom Left) | EZ_BC (Bottom Center) | EZ_BR (Bottom Right) |
Le texte est tracé par dessus le dessin actuel ; on peut aussi faire effacer le fond en même temps (avec du blanc) en utilisant pour align les constantes :
EZ_TLF (Top Left Filled) | EZ_TCF (Top Center Filled) | EZ_TRF (Top Right Filled) |
EZ_MLF (Middle Left Filled) | EZ_MCF (Middle Center Filled) | EZ_MRF (Middle Right Filled) |
EZ_BLF (Bottom Left Filled) | EZ_BCF (Bottom Center Filled) | EZ_BRF (Bottom Right Filled) |
L’affichage avec double-buffer permet d’éviter que la fenêtre ne clignote pendant qu’elle est rafraichie. Le principe est de dessiner dans le double-buffer, puis d’échanger celui-ci avec le contenu de la fenêtre quand tous les dessins sont finis. Tout est automatiquement géré par EZ-Draw.
Active ou inactive l’affichage double-buffer pour le window win.
Par défaut, l’affichage double-buffer est désactivé (val = 0).
Si l’affichage double-buffer est activé (val = 1) pour un window, les dessins dans ce window doivent obligatoirement être faits uniquement lors des évènements Expose de ce window. Si le double-buffer est inactivé, ce n’est plus une obligation, mais cela reste fortement conseillé.
Comme exemple, voir dans jeu-nim.c les fonctions gui_init(), win1_onKeyPress(), win1_onExpose().
Dans ce jeu, on peut tester l’affichage avec et sans le double-buffer (presser la lettre d pour basculer entre l’un et l’autre) :
Armer un timer signifie mémoriser une date dans le futur, qui est la date actuelle plus un certain délai. Lorsqu’on arrive à cette date future, on dit que le timer est arrivé à échéance.
Chaque fenêtre peut être associée à un timer. À l’échéance du timer, l’application reçoit un évènement unique TimerNotify pour le window concerné, puis le timer est supprimé.
Arme un timer pour le window win avec un délai delay en millisecondes.
Tout rappel de cette fonction avant l’échéance du timer annule et remplace le timer. Si de plus delay vaut -1, alors le timer est supprimé (remarque : ce n’est pas une erreur de supprimer un timer déjà supprimé ou inexistant).
Comme exemple, voir demo-09.c.
Chaque fenêtre peut mémoriser une donnée arbitraire du programme, par exemple une chaîne de caractères ou l’adresse d’un struct. On peut ensuite récupérer cette donnée à tout moment dans le programme. Ce mécanisme permet ainsi d’éviter l’emploi de variables globales.
Voici un exemple de programme qui affiche un cercle, dont les coordonnées sont placées dans une variable globale md :
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 | #include "ez-draw.h"
typedef struct {
int x, y, r;
} Mes_donnees;
Mes_donnees md; /* 1. Variable globale */
void win1_on_expose (Ez_event *ev)
{
/* 3. Utilisation */
ez_draw_circle (ev->win, md.x-md.r, md.y-md.r, md.x+md.r, md.y+md.r);
}
void win1_event (Ez_event *ev)
{
switch (ev->type) {
case Expose : win1_on_expose (ev); break;
}
}
int main ()
{
if (ez_init() < 0) exit(1);
/* 2. Initialisation */
md.x = 200; md.y = 100; md.r = 50;
ez_window_create (400, 300, "Demo client-data 1", win1_event);
ez_main_loop ();
exit(0);
}
|
Voici maintenant le même programme sans variable globale, en mémorisant la donnée dans la fenêtre :
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 | #include "ez-draw.h"
typedef struct {
int x, y, r;
} Mes_donnees;
void win1_on_expose (Ez_event *ev)
{
/* 4. On retrouve les données attachées à la fenêtre */
Mes_donnees *md = ez_get_data (ev->win);
/* 5. Utilisation */
ez_draw_circle (ev->win, md->x-md->r, md->y-md->r, md->x+md->r, md->y+md->r);
}
void win1_event (Ez_event *ev)
{
switch (ev->type) {
case Expose : win1_on_expose (ev); break;
}
}
int main ()
{
Ez_window win1;
Mes_donnees md; /* 1. Variable locale à main() */
if (ez_init() < 0) exit(1);
/* 2. Initialisation */
md.x = 200; md.y = 100; md.r = 50;
win1 = ez_window_create (400, 300, "Demo client-data 2", win1_event);
/* 3. On mémorise la donnée dans la fenêtre */
ez_set_data (win1, &md);
ez_main_loop ();
exit(0);
}
|
Comme autre exemple, voir demo-10.c.
EZ-Draw permet d’afficher ou de manipuler des images avec le type suivant :
Type struct pour mémoriser et manipuler une image.
Ce type est défini dans ez-image.h de la façon suivante :
typedef struct {
int width, height;
Ez_uint8 *pixels_rgba;
int has_alpha;
int opacity;
} Ez_image;
La largeur de l’image en pixels est width et sa hauteur est height.
Les pixels sont mémorisés dans le tableau pixels_rgba sous la forme R,G,B,A (pour rouge, vert, bleu, alpha, c’est-à-dire transparence) avec une valeur entre 0 et 255 (255 est l’intensité ou l’opacité maximale).
Les valeurs R,G,B,A d’un pixel de coordonnées x,y dans l’image sont mémorisées dans pixels_rgba[(y*width+x)*4 + 0..3].
Le champ has_alpha indique si le canal alpha est utilisé (has_alpha = 1) ou ignoré (has_alpha = 0) lors de l’affichage. Si le canal est ignoré, tous les pixels seront affichés ; s’il est utilisé, seuls les pixels opaques seront affichés.
Les pixels opaques sont les pixels dont le canal alpha est supérieur ou égal au seuil d’opacité, stipulé par le champ opacity ; par défaut le seuil d’opacité est 128.
Pour utiliser les fonctions suivantes il faut inclure ez-image.h.
Crée une image de largeur w et hauteur h en pixels.
Renvoie un pointeur sur l’image créée, ou NULL si erreur.
Charge une image depuis le fichier filename. Le fichier doit être au format PNG, JPEG, GIF ou BMP.
La transparence est gérée pour les formats PNG, GIF et BMP : si le fichier contient un canal alpha, le champ has_alpha de l’image est mis à 1.
Renvoie un pointeur sur l’image créée, ou NULL si erreur.
Créée une copie profonde de l’image img.
Renvoie un pointeur sur l’image créée, ou NULL si erreur.
Détruit une image en mémoire.
Toutes les images créées par les fonctions ez_image_... doivent être libérées avec cette fonction.
Affiche une image dans la fenêtre win, avec le coin supérieur gauche de l’image aux coordonnées x,y dans la fenêtre. Si img->has_alpha est vrai, applique la transparence, c’est-à-dire n’affiche que les pixels opaques.
Affiche une région rectangulaire d’une image dans la fenêtre win.
La région de l’image est délimitée par les coordonnées src_x, src_y (coin supérieur gauche) et src_x+w-1, src_y+h-1 (coin inférieur droit) dans l’image. Si les coordonnées dépassent l’image, seule la région appartenant effectivement à l’image est affichée.
Le coin supérieur gauche de la région est affiché aux coordonnées x,y dans la fenêtre. Si img->has_alpha est vrai, applique la transparence.
Affiche une région rectangulaire d’une image dans le terminal.
La région de l’image img est délimitée par les coordonnées src_x, src_y (coin supérieur gauche) et src_x+w-1, src_y+h-1 (coin inférieur droit) dans img. Si les coordonnées dépassent l’image, seule la région appartenant effectivement à l’image est affichée.
Cette section présente quelques opérations disponibles en incluant ez-image.h. Ces opérations sont faites sur les couleurs et sur le canal alpha.
Remplit une image avec une couleur r,g,b,a.
Les valeurs sont entre 0 et 255.
Incruste une région de l’image src dans l’image dst.
La région de l’image source src est délimitée par les coordonnées src_x, src_y (coin supérieur gauche) et src_x+w-1, src_y+h-1 (coin inférieur droit). Cette région est incrustée dans l’image destination dst aux coordonnées dst_x, dst_y (coin supérieur gauche) et dst_x+w-1, dst_y+h-1 (coin inférieur droit).
Si les coordonnées dépassent les images src ou dst, seule la région commune est incrustée. Si l’image source n’a pas de canal alpha (c’est-à-dire si src->has_alpha est faux), alors les valeurs de la région de src écrasent celle de dst. Dans le cas contraîre, les régions sont mélangées par transparence (alpha blending) avec les formules de Porter et Duff.
Crée une image contenant une copie d’une région rectangulaire de l’image source img.
La région de l’image est délimitée par les coordonnées src_x, src_y (coin supérieur gauche) et src_x+w-1, src_y+h-1 (coin inférieur droit) dans img. Si les coordonnées dépassent l’image, seule la région appartenant effectivement à l’image est extraite.
Renvoie NULL en cas d’erreur mémoire ou si l’intersection est vide.
Crée une image de même taille et propriétés que l’image source img, contenant le symétrique de l’image par rapport à l’axe vertical ou horizontal.
Renvoie la nouvelle image, ou NULL si erreur.
Crée une image de taille multipliée par factor pour l’image source img, contenant l’image mise à l’échelle. Le facteur d’échelle factor doit être strictement positif.
Renvoie la nouvelle image, ou NULL si erreur.
Effectue une rotation de l’image source img d’angle theta en degrés. Renvoie une nouvelle image dont la taille est ajustée pour contenir le résultat, ou NULL en cas d’erreur.
Dans l’image résultat, le champs has_alpha est mis à 1, et les parties ne provenant pas de l’image source sont transparentes ; le but est qu’elles n’apparaissent pas lors de l’affichage.
Si quality = 1, l’algorithme utilisé lisse le résultat (avec une interpolation bilinéaire) ; si quality = 0, l’algorithme privilégie la rapidité (avec un calcul de plus proche voisin), ce qui permet de gagner environ un facteur 3.
Calcule pour un point de coordonnées src_x,src_y dans l’image source, les nouvelles coordonnées dst_x,dst_y du point correspondant dans l’image résultat.
L’exemple demo-16.c illustre les rotations, sans ou avec transparence. Le centre de rotation (croix rouge) est déplaçable avec les flèches. On peut aussi modifier la qualité.
On obtient ces fenêtres :
Nous avons vu dans les sections précédentes le type Ez_image défini dans ez-image.h.
Ce type est commode pour charger des images, les transformer, les afficher. Toutefois, l’affichage d’une image prend quelques millisecondes à quelques dizaines de millisecondes, durée variable selon la taille de l’image et la puissance de la machine. La raison en est qu’à chaque affichage, ez_image_paint() refait toute la conversion depuis le type Ez_image en une image intermédiaire en mémoire, applique la transparence éventuelle, envoie le résultat à la carte graphique qui enfin l’affiche.
On peut afficher la durée des opérations dans le terminal, en définissant une variable d’environnement puis en relançant une démo : sous Unix, taper
export EZ_IMAGE_DEBUG=1
ou sous Windows, taper
set EZ_IMAGE_DEBUG=1
On obtient par exemple sous Unix :
$ ./demo-14
ez_image_load file "images/paper1.jpg" in 8.725 ms w = 640 h = 480 n = 3 has_alpha = 0
ez_image_load file "images/tux1.png" in 1.946 ms w = 210 h = 214 n = 4 has_alpha = 1
ez_xi_create w = 640 h = 480 depth = 24 bpp = 32
ez_xi_fill_24 2.875 ms
ez_xi_create w = 210 h = 214 depth = 24 bpp = 32
ez_xi_fill_24 0.132 ms
ez_xmask_create fill 0.119 ms bitmap 5.610 ms
Pour supprimer cette variable d’environnement sous Unix, taper
unset EZ_IMAGE_DEBUG
ou sous Windows, taper
set EZ_IMAGE_DEBUG=
Dans une animation, tous ces temps s’additionnent, et lorsqu’il y a beaucoup d’images, l’animation risque d’être saccadée. La solution est simple : convertir l’image de type Ez_image en un pixmap de type Ez_pixmap, puis afficher le pixmap.
Un pixmap est une image déjà convertie et stockée dans la carte graphique. Son affichage est donc beaucoup plus rapide, et de plus soulage le processeur de la machine.
Une fois créé, un pixmap est non modifiable.
Cette solution est aussi intéressante pour afficher une image de fond (qui est souvent de taille importante). Dans ce cas, on gagne encore en efficacité en utilisant une image sans canal alpha.
Le type Ez_pixmap est défini comme ceci :
typedef struct {
int width, height;
/* autres champs privés */
} Ez_pixmap
Les fonctions suivantes manipulent les pixmaps :
Crée un pixmap à partir d’une image img. Le pixmap conserve la transparence de l’image. L’image peut ensuite être libérée s’il n’y en a plus besoin.
Renvoie le nouveau pixmap, ou NULL si erreur.
Détruit le pixmap pix.
Les pixmaps doivent être détruits par cette fonction.
Affiche le pixmap pix dans la fenêtre win.
Le coin supérieur gauche du pixmap est affiché aux coordonnées x,y dans la fenêtre.
Affiche le pixmap pix de manière répétitive dans la fenêtre win.
Le pixmap est affiché à la manière d’un papier peint dans la zone de la fenêtre délimitée par les coordonnées x,y (coin supérieur gauche) et x+w-1,y+h-1 (coin inférieur droit).
L’exemple demo-17.c permet de tester la vitesse d’affichage, mesurée en fps (pour frame per second) dans une animation. Utiliser les touches + et - pour modifier le nombre de balles, et la touche p pour activer l’utilisation des pixmaps.
On obtient cette fenêtre :
Renvoie un entier aléatoire entre 0 et n-1.
Remarque : le générateur de nombres aléatoires est initialisé par ez_init().
Renvoie le temps écoulé depuis l’Epoch (le 1er janvier 1970 à 0h) en secondes avec une précision en microsecondes.
Cette fonction est utile pour mesurer la durée d’un calcul : il suffit d’appeler ez_get_time() avant et après le calcul, puis d’afficher la différence :
double t1, t2;
t1 = ez_get_time ();
calcul ();
t2 = ez_get_time ();
printf ("Durée du calcul : %.6f s\n", t2-t1)