The easiest way to proceed is to copy the files ez-draw.h and ez-draw.c in your directory, then create your programs there.
You may also write you programs directly in the EZ-Draw directory, and simply add the executable file names in the Makefile (on Unix) or Makefile.win (on Windows), see section Compilation.
Let us write our first program that opens a window, and name it demo-01.c. We first include ez-draw.h (line 1, see below): this file defines the types and prototypes of the main EZ-Draw module, and it also includes the standard headers such as <stdio.h>, <stdlib.h>, <string.h>, so we don’t need to worry about.
In main, we initialize the module and the graphic mode by calling ez_init(); if the initialization fails, the function print an error message in the terminal, then return -1. In this case, we must terminate the program by exit(1) .
Next we create one (or several) window(s) using function ez_window_create(). These windows are displayed when the program reaches ez_main_loop(): that is this function which “gives life” to the windows. It stops when one calls ez_quit(), or when all windows are destroyed.
Here is the file demo-01.c :
1 2 3 4 5 6 7 8 9 10 11 12 | #include "ez-draw.h"
int main ()
{
if (ez_init() < 0) exit(1);
ez_window_create (400, 300, "Demo 01 : Hello World", NULL);
ez_main_loop ();
exit(0);
}
|
This window is obtained:
To compile the previous example demo-01.c on Unix, type
gcc -Wall demo-01.c ez-draw.c -o demo-01 -lX11 -lXext -L/usr/X11R6/lib
or on Windows, type
gcc -Wall demo-01.c ez-draw.c -o demo-01.exe -lgdi32
You can also add the executable file name at the end of EXECS = in the Makefile on Unix or Makefile.win on Windows; then type make all to compile.
To run the program in a terminal on Unix, type
./demo-01
or on Windows, type
demo-01
The parameters of the function ez_window_create() which is responsible of the windows creation are:
Ez_window ez_window_create (int w, int h, const char *name, Ez_func func);
w is the width of the interior of the window in pixels, h is the height, name is the window title; func is the event handler of the window, see below.
The result of ez_window_create() is a number which identifies the window, of type Ez_window; it can be printed in the terminal:
Ez_window win1;
win1 = ez_window_create (400, 300, "Demo 0 : Hello World", NULL);
printf ("win1 = 0x%x\n", (int) win1);
To be able to interact with the user (key press and release, mouse moves and click, etc) we have to realize a so-called event handling; that is why we give the function func as a fourth parameter of ez_window_create().
The event handler func (also named callback), is a function of your program (or NULL as in example demo-01). This function will be automatically called by ez_main_loop() for each event that involves the window.
The function func has the following prototype:
void func (Ez_event *ev);
The parameter ev is the address of a struct whose fields describe the event; in particular, ev->win tells which window is involved. The other fields are detailed in section Tracing events.
We study two events in the following example demo-02.c :
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 | #include "ez-draw.h"
void win1_event (Ez_event *ev) /* Appele'e a chaque evenement sur win1 */
{ /* par ez_main_loop() */
switch (ev->type) {
case Expose : /* Il faut tout redessiner */
ez_set_color (ez_red);
ez_draw_text (ev->win, EZ_MC, 200, 150,
"Pour quitter, tapez sur la touche 'q', ou\n"
"cliquez sur l'icone fermeture de la fenetre");
break;
case KeyPress : /* Une touche a ete pressee */
switch (ev->key_sym) {
case XK_q : ez_quit (); break;
}
break;
}
}
int main ()
{
if (ez_init() < 0) exit(1);
ez_window_create (400, 300, "Demo 02 : fenetre et evenements", win1_event);
ez_main_loop ();
exit(0);
}
|
This window is obtained:
As explained in the previous section, the Expose event means that the whole content of the windows must be redrawn. In the next example we redraw by calling win1_on_expose. Note: for each Expose event, EZ-Draw empties the window (with a white background) before passing the event to your program.
The list of drawings is given in section Drawings. The coordinates are relative to the Origin, which is the top left corner inside the window; x goes to the right and y goes down.
The drawings are automatically cut by the window border, so that there is no need to worry if a drawing fits or not.
The drawings are performed using the current thickness (1 pixel by default). you can change the thickness with ez_set_thick(), see Drawings.
The drawings are done in the current color (black by default). To change color, call ez_set_color() by giving it the color number. Some colors are predefined: ez_black, ez_white, ez_grey, ez_red, ez_green, ez_blue, ez_yellow, ez_cyan, ez_magenta. It is possible to create other colors, see Colors.
Here is the file demo-03.c :
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 | #include "ez-draw.h"
void win1_on_expose (Ez_event *ev)
{
ez_set_color (ez_magenta);
ez_draw_text (ev->win, EZ_BL, 10, 20, "draw epaisseur 1 :");
ez_set_thick (1);
ez_draw_point (ev->win, 30, 50);
ez_draw_line (ev->win, 60, 35, 130, 70);
ez_draw_rectangle (ev->win, 160, 30, 220, 70);
ez_draw_circle (ev->win, 240, 30, 300, 70);
ez_draw_triangle (ev->win, 320, 30, 380, 40, 350, 70);
ez_set_color (ez_black);
ez_draw_text (ev->win, EZ_BL, 10, 100, "draw epaisseur 2 :");
ez_set_color (ez_cyan);
ez_set_thick (2);
ez_draw_point (ev->win, 30, 130);
ez_draw_line (ev->win, 60, 115, 130, 150);
ez_draw_rectangle (ev->win, 160, 110, 220, 150);
ez_draw_circle (ev->win, 240, 110, 300, 150);
ez_draw_triangle (ev->win, 320, 110, 380, 120, 350, 150);
ez_set_color (ez_blue);
ez_draw_text (ev->win, EZ_BL, 10, 180, "draw epaisseur 9 :");
ez_set_color (ez_green);
ez_set_thick (9);
ez_draw_point (ev->win, 30, 210);
ez_draw_line (ev->win, 60, 195, 130, 230);
ez_draw_rectangle (ev->win, 160, 190, 220, 230);
ez_draw_circle (ev->win, 240, 190, 300, 230);
ez_draw_triangle (ev->win, 320, 190, 380, 200, 350, 230);
ez_set_color (ez_red);
ez_draw_text (ev->win, EZ_BL, 10, 260, "fill :");
ez_set_color (ez_yellow);
ez_fill_rectangle (ev->win, 160, 270, 220, 310);
ez_fill_circle (ev->win, 240, 270, 300, 310);
ez_fill_triangle (ev->win, 320, 270, 380, 280, 350, 310);
}
void win1_on_key_press (Ez_event *ev)
{
switch (ev->key_sym) {
case XK_q : ez_quit (); break;
}
}
void win1_event (Ez_event *ev)
{
switch (ev->type) {
case Expose : win1_on_expose (ev); break;
case KeyPress : win1_on_key_press (ev); break;
}
}
int main ()
{
if (ez_init() < 0) exit(1);
ez_window_create (400, 320, "Demo 03 : tous les dessins", win1_event);
ez_main_loop ();
exit(0);
}
|
This window is obtained:
It is possible to draw text at any place in the window, thanks to the function ez_draw_text(). It takes as arguments: the window, the kind of alignment align, the coordinates x1,y1, finally a string to draw, or as in printf, a format and parameters. Everything is detailed in section Text and fonts.
The string can contain some \n, causing line breaks in the display. The text drawing is performed in the current color, modifiable by ez_set_color().
In the next example demo-04.c we illustrate this, as well as the use of ez_window_get_size() to kindly adapt the drawing to the window size changes.
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 | #include "ez-draw.h"
void win1_on_expose (Ez_event *ev)
{
int i, w, h;
ez_window_get_size (ev->win, &w, &h);
ez_set_color (ez_black);
for (i = 0; i <= 3; i++) {
ez_set_nfont (i);
ez_draw_text (ev->win, EZ_TC, w/2, h/2 + 25*(i-2),
"Fonte numero %d", i); /* comme un printf */
}
ez_set_nfont (0);
ez_set_color (ez_red);
ez_draw_text (ev->win, EZ_TL, 2, 1, "Top\nLeft");
ez_draw_text (ev->win, EZ_TC, w/2, 1, "Top\nCenter");
ez_draw_text (ev->win, EZ_TR, w-2, 1, "Top\nRight");
ez_draw_text (ev->win, EZ_ML, 2, h/2, "Middle\nLeft");
ez_draw_text (ev->win, EZ_MR, w-2, h/2, "Middle\nRight");
ez_draw_text (ev->win, EZ_BL, 2, h-2, "Bottom\nLeft");
ez_draw_text (ev->win, EZ_BC, w/2, h-2, "Bottom\nCenter");
ez_draw_text (ev->win, EZ_BR, w-2, h-2, "Bottom\nRight");
}
void win1_on_key_press (Ez_event *ev)
{
switch (ev->key_sym) {
case XK_q : ez_quit (); break;
}
}
void win1_event (Ez_event *ev)
{
switch (ev->type) {
case Expose : win1_on_expose (ev); break;
case KeyPress : win1_on_key_press (ev); break;
}
}
int main ()
{
if (ez_init() < 0) exit(1);
ez_window_create (400, 300, "Demo 04 : affichage de texte", win1_event);
ez_main_loop ();
exit(0);
}
|
This window is obtained:
In the next example we list all possible events, and we trace in the terminal the ev variable fields that are usable (the other ones are set to 0). See also section Events.
By default, the “Close” button in the title bar of one of the application windows causes the termination of the program. We can change this behavior by calling ez_auto_quit(0) : from now on, the “Close” button will cause a WindowClose event, as in the following example.
Here is the file demo-05.c :
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 | #include "ez-draw.h"
void win1_on_expose (Ez_event *ev) /* Il faut tout redessiner */
{
ez_draw_text (ev->win, EZ_MC, 200, 150,
"L'affichage des evenements\nest fait dans la console.\n\n"
"Tapez 'q' pour quitter.");
printf ("Expose win = 0x%x\n", (int) ev->win);
}
void win1_on_button_press (Ez_event *ev) /* Bouton souris enfonce' */
{
printf ("ButtonPress win = 0x%x mx = %d my = %d mb = %d\n",
(int) ev->win, ev->mx, ev->my, ev->mb);
}
void win1_on_button_release (Ez_event *ev) /* Bouton souris relache' */
{
printf ("ButtonRelease win = 0x%x mx = %d my = %d mb = %d\n",
(int) ev->win, ev->mx, ev->my, ev->mb);
}
void win1_on_motion_notify (Ez_event *ev) /* Souris deplace'e */
{
printf ("MotionNotify win = 0x%x mx = %d my = %d mb = %d\n",
(int) ev->win, ev->mx, ev->my, ev->mb);
}
void win1_on_key_press (Ez_event *ev) /* Touche clavier enfonce'e */
{
printf ("KeyPress win = 0x%x mx = %d my = %d "
"key_sym = 0x%x key_name = %s key_count = %d key_string = \"%s\"\n",
(int) ev->win, ev->mx, ev->my,
(int) ev->key_sym, ev->key_name, ev->key_count,
ev->key_sym == XK_Return || ev->key_sym == XK_KP_Enter ? "" : ev->key_string);
}
void win1_on_key_release (Ez_event *ev) /* Touche clavier relache'e */
{
printf ("KeyRelease win = 0x%x mx = %d my = %d "
"key_sym = 0x%x key_name = %s key_count = %d key_string = \"%s\"\n",
(int) ev->win, ev->mx, ev->my,
(int) ev->key_sym, ev->key_name, ev->key_count,
ev->key_sym == XK_Return || ev->key_sym == XK_KP_Enter ? "" : ev->key_string);
switch (ev->key_sym) {
case XK_q : ez_quit (); break;
}
}
void win1_on_configure_notify (Ez_event *ev) /* Taille fenetre modifie'e */
{
printf ("ConfigureNotify win = 0x%x width = %d height = %d\n",
(int) ev->win, ev->width, ev->height);
}
void win1_on_window_close (Ez_event *ev) /* Fermeture fenetre intercepte'e */
{
printf ("WindowClose win = 0x%x\n", (int) ev->win);
}
void win1_event (Ez_event *ev) /* Appele'e a chaque evenement sur win1 */
{
switch (ev->type) {
case Expose : win1_on_expose (ev); break;
case ButtonPress : win1_on_button_press (ev); break;
case ButtonRelease : win1_on_button_release (ev); break;
case MotionNotify : win1_on_motion_notify (ev); break;
case KeyPress : win1_on_key_press (ev); break;
case KeyRelease : win1_on_key_release (ev); break;
case ConfigureNotify : win1_on_configure_notify (ev); break;
case WindowClose : win1_on_window_close (ev); break;
default :
printf ("Evenement inconnu : %d\n", ev->type);
}
}
int main ()
{
if (ez_init() < 0) exit(1);
ez_window_create (400, 300, "Demo 05 : trace les evenements", win1_event);
ez_auto_quit (0); /* pour capter l'evenement WindowClose */
ez_main_loop ();
exit(0);
}
|
This window is obtained:
Note: the TimerNotify events are not treated here, see Timers.
The example shown in this section allows to draw a polygonal line with the mouse. The coordinates of the vertices are stored in global variables. Each time the mouse button is clicked, a new vertex is inserted; for each mouse move with a pressed button (drag), the last vertex is moved.
By principle (and for technical reasons), the drawings must only be done for the Expose event. If you want to update the drawings of a window for another event, it is sufficient to send an Expose event using the function ez_send_expose(). We do this here, for ButtonPress, MotionNotify and KeyPress events.
Here is the file demo-06.c :
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 | #include "ez-draw.h"
#define SOM_MAX 100
int som_nb = 0, som_x[SOM_MAX], som_y[SOM_MAX];
void sommet_vider ()
{
som_nb = 0;
}
void sommet_ajouter (int x, int y)
{
if (som_nb >= SOM_MAX) return;
som_x[som_nb] = x;
som_y[som_nb] = y;
som_nb++;
}
void sommet_deplacer (int x, int y)
{
if (som_nb <= 0 || som_nb >= SOM_MAX) return;
som_x[som_nb-1] = x;
som_y[som_nb-1] = y;
}
void sommet_dessiner (Ez_window win)
{
int i;
/* On dessine les sommets */
ez_set_color (ez_blue);
for (i = 0; i < som_nb; i++)
ez_draw_rectangle (win, som_x[i]-2, som_y[i]-2, som_x[i]+2, som_y[i]+2);
/* On relie les sommets par des segments */
ez_set_color (ez_grey);
for (i = 1; i < som_nb; i++)
ez_draw_line (win, som_x[i-1], som_y[i-1], som_x[i], som_y[i]);
}
void win1_on_expose (Ez_event *ev)
{
ez_set_color (ez_black);
ez_draw_text (ev->win, EZ_TL, 10, 10,
"Cliquez et tirez la souris dans la fenetre pour dessiner.\n"
"Tapez sur espace pour vider la fenetre, 'q' pour quitter.");
sommet_dessiner (ev->win);
}
void win1_on_button_press (Ez_event *ev)
{
sommet_ajouter (ev->mx, ev->my);
ez_send_expose (ev->win);
}
void win1_on_motion_notify (Ez_event *ev)
{
if (ev->mb == 0) return; /* pas de bouton enfonce' */
sommet_deplacer (ev->mx, ev->my);
ez_send_expose (ev->win);
}
void win1_on_key_press (Ez_event *ev)
{
switch (ev->key_sym) {
case XK_q :
ez_quit ();
break;
case XK_space :
sommet_vider ();
ez_send_expose (ev->win);
break;
}
}
void win1_event (Ez_event *ev)
{
switch (ev->type) {
case Expose : win1_on_expose (ev); break;
case ButtonPress : win1_on_button_press (ev); break;
case MotionNotify : win1_on_motion_notify (ev); break;
case KeyPress : win1_on_key_press (ev); break;
}
}
int main ()
{
Ez_window win1;
if (ez_init() < 0) exit(1);
win1 = ez_window_create (400, 300, "Demo 06 : dessin a la souris", win1_event);
/* On associe un double-buffer d'affichage pour eviter tout clignotement */
ez_window_dbuf (win1, 1);
ez_main_loop ();
exit(0);
}
|
This window is obtained:
You can create as much windows that you want, by calling ez_window_create(). Each window that is created is immediately displayed on top of the existing windows. To destroy a window win (and thus hide it from screen), use ez_window_destroy(win).
It is possible to hide a window win (it still exists but is not displayed) by calling ez_window_show(win, 0), then show it again (on top of the other ones) by calling ez_window_show(win, 1).
In the next example, the main loop is configured by ez_auto_quit(0), which means that pressing the “Close” button of the window title bar will not end the program, but send in place a WindowClose event. According to the window involved, we hide the window, destroy the window or exit the program.
Here is the file demo-07.c :
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 | #include "ez-draw.h"
/* En global */
Ez_window win1, win2, win3 = None; int show2 = 0;
void win3_on_expose (Ez_event *ev)
{
ez_draw_text (ev->win, EZ_TL, 10, 10,
"Si vous fermez cette fenetre, elle sera detruite.");
}
/* L'utilisateur a clique' sur l'icone fermeture de la fenetre */
void win3_on_window_close (Ez_event *ev)
{
(void) ev; /* Parametre inutilise' */
ez_window_destroy (win3); win3 = None;
}
void win3_event (Ez_event *ev)
{
switch (ev->type) {
case Expose : win3_on_expose (ev); break;
case WindowClose : win3_on_window_close (ev); break;
}
}
void win2_on_expose (Ez_event *ev)
{
ez_draw_text (ev->win, EZ_TL, 10, 10,
"Si vous fermez cette fenetre, elle sera simplement cachee.");
}
void win2_on_window_close (Ez_event *ev)
{
(void) ev;
ez_window_show (win2, 0); show2 = 0;
}
void win2_event (Ez_event *ev)
{
switch (ev->type) {
case Expose : win2_on_expose (ev); break;
case WindowClose : win2_on_window_close (ev); break;
}
}
void win1_on_expose (Ez_event *ev)
{
ez_draw_text (ev->win, EZ_TL, 10, 10,
"Cliquez dans cette fenetre (pour donner le focus clavier),\n"
"puis tapez :\n"
" - sur 'm' pour montrer ou cacher la fenetre 2 ;\n"
" - sur 'c' pour creer ou detruire la fenetre 3 ;\n"
" - sur 'q' pour quitter.\n"
"\n"
"Si vous fermez cette fenetre, le programme se terminera.");
}
void win1_on_key_press (Ez_event *ev)
{
switch (ev->key_sym) {
case XK_q : ez_quit (); break;
case XK_m :
show2 = !show2; /* on affiche ou on cache la fenetre */
ez_window_show (win2, show2);
break;
case XK_c :
if (win3 == None) /* si la fenetre n'existe pas, on la cree */
win3 = ez_window_create (380, 220, "Fenetre 3", win3_event);
else { ez_window_destroy (win3); win3 = None; }
break;
}
}
void win1_on_window_close (Ez_event *ev)
{
(void) ev;
ez_quit ();
}
void win1_event (Ez_event *ev)
{
switch (ev->type) {
case Expose : win1_on_expose (ev); break;
case KeyPress : win1_on_key_press (ev); break;
case WindowClose : win1_on_window_close (ev); break;
}
}
int main ()
{
if (ez_init() < 0) exit(1);
win1 = ez_window_create (400, 300, "Demo 07 : plusieurs fenetres", win1_event);
win2 = ez_window_create (400, 200, "Fenetre 2", win2_event);
ez_window_show (win2, show2);
/* Par defaut, fermer n'importe quelle fenetre provoque la fin du programme.
On desactive cette fin automatique ; fermer une fenetre provoquera alors
l'evenement WindowClose pour ce window. */
ez_auto_quit (0);
ez_main_loop ();
exit(0);
}
|
This window is obtained:
The next example demo-08.c demonstrates how to read a string on keyboard, suppress some characters using the Backspace, and detect the Enter key to trigger an action.
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 | #include "ez-draw.h"
#define BUF_MAX 80
char buf1[BUF_MAX] = "", buf2[BUF_MAX] = "";
/* Renvoie 1 si l'affichage doit etre refait, 2 si texte valide', 0 sinon */
int texte_saisir (Ez_event *ev, char *s)
{
int i;
switch (ev->key_sym) {
case XK_BackSpace : /* Touche backspace */
i = strlen (s);
if (i == 0) break;
s[i-1] = 0;
return 1;
case XK_Return : /* Touche Entree */
return 2;
default : /* Insertion d'un caractere */
if (ev->key_count != 1) break;
i = strlen (s);
if (i >= BUF_MAX-1) break;
s[i] = ev->key_string[0]; s[i+1] = 0;
return 1;
}
return 0;
}
void texte_afficher (Ez_window win, int x, int y, char *s1, char *s2)
{
ez_set_color (ez_black);
ez_draw_text (win, EZ_TL, x, y, "Texte : %s_", s1);
if (strcmp (buf2, "") != 0) {
ez_set_color (ez_red);
ez_draw_text (win, EZ_TC, 200, 70,
"Vous avez valide le texte :\n%s", s2);
}
}
void win1_on_expose (Ez_event *ev)
{
texte_afficher (ev->win, 10, 10, buf1, buf2);
}
void win1_on_key_press (Ez_event *ev)
{
int k = texte_saisir (ev, buf1);
if (k == 2) strncpy (buf2, buf1, BUF_MAX);
if (k > 0) ez_send_expose (ev->win);
}
void win1_event (Ez_event *ev)
{
switch (ev->type) {
case Expose : win1_on_expose (ev); break;
case KeyPress : win1_on_key_press (ev); break;
}
}
int main ()
{
if (ez_init() < 0) exit(1);
ez_window_create (400, 200, "Demo 08 : saisie de texte", win1_event);
ez_main_loop ();
exit(0);
}
|
This window is obtained:
To perform animations, two additional ingredients are needed: a timer (see Timers) to maintain the temporal sequence, and double buffering (see Double buffering) to prevent display flashing.
The principle of an animation is the following:
Here is a first example demo-09.c below. The animation shows a growing circle at the middle of the window; it also adapts the drawings to the window size changes.
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 | #include "ez-draw.h"
#define MAX_CPT1 100
/* On peut eviter ces variables globales avec ez_set_data(), voir demo-10.c
et suivantes. */
int cpt1 = 0, win1_w = 300, win1_h = 200, delay1 = 30;
void win1_on_expose (Ez_event *ev)
{
/* On fait le dessin en fonction de cpt1 */
int xc = win1_w/2, rx = xc * cpt1 / MAX_CPT1,
yc = win1_h/2, ry = yc * cpt1 / MAX_CPT1;
ez_set_color (ez_magenta);
ez_set_thick (3);
ez_draw_circle (ev->win, xc-rx, yc-ry, xc+rx, yc+ry);
ez_set_color (ez_black); ez_set_nfont (0);
ez_draw_text (ev->win, EZ_BL, 8, win1_h-8, "q : quitter");
}
void win1_on_key_press (Ez_event *ev)
{
switch (ev->key_sym) {
case XK_q : ez_quit (); break;
}
}
void win1_on_configure_notify (Ez_event *ev)
{
win1_w = ev->width; win1_h = ev->height;
}
void win1_on_timer_notify (Ez_event *ev) /* Le timer est arrive' a echance */
{
/* On incremente le compteur cpt1 pour modifier la position de l'objet
que l'on veut animer */
cpt1 = (cpt1 + 1) % MAX_CPT1;
/* On envoie l'evenement Expose pour que la fenetre soit redessinee */
ez_send_expose (ev->win);
/* On re'arme le timer, pour entretenir une "boucle" de TimerNotify
qui est iteree tous les delay1 millisecondes */
ez_start_timer (ev->win, delay1);
}
void win1_event (Ez_event *ev)
{
switch (ev->type) {
case Expose : win1_on_expose (ev); break;
case KeyPress : win1_on_key_press (ev); break;
case ConfigureNotify : win1_on_configure_notify (ev); break;
case TimerNotify : win1_on_timer_notify (ev); break;
}
}
int main ()
{
Ez_window win1;
if (ez_init() < 0) exit(1);
win1 = ez_window_create (win1_w, win1_h, "Demo 09 : hypnose", win1_event);
/* On associe un double-buffer d'affichage pour eviter tout clignotement */
ez_window_dbuf (win1, 1);
/* Provoque l'envoie d'un evenement TimerNotify dans delay1 millisecondes :
c'est le point de depart de la "boucle" de TimerNotify */
ez_start_timer (win1, delay1);
ez_main_loop ();
exit(0);
}
|
This window is obtained:
Another example is provided by demo-10.c to illustrate multiple animations: in one window we turn the hands of a watch (type space for pause), while in another window a ball is bouncing on a racket (the window can be enlarged).
These windows are obtained:
In the previous chapters we have seen what we can do with the basic module.
EZ-Draw comes with a second module, ez-image.c, that allows to load and display color images in PNG, JPEG, GIF or BMP format, or create an image in memory and draw into. These possibilities are detailed in sections The image type and following.
To use this module, just include ez-image.h. Here is the example demo-13.c where we get a file name as argument of the command line, then we load the image and display it:
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 | #include "ez-draw.h"
#include "ez-image.h"
typedef struct {
Ez_image *image1;
Ez_window win1;
} App_data;
void app_data_init (App_data *a, char *filename)
{
a->image1 = ez_image_load (filename); /* Charge une image */
if (a->image1 == NULL) exit (1);
}
void app_data_destroy (App_data *a)
{
ez_image_destroy (a->image1); /* Detruit l'image */
}
void win1_on_expose (Ez_event *ev)
{
App_data *a = ez_get_data (ev->win);
ez_image_paint (a->win1, a->image1, 0, 0); /* Affiche l'image */
}
void win1_on_key_press (Ez_event *ev)
{
switch (ev->key_sym) {
case XK_q : ez_quit (); break;
}
}
void win1_event (Ez_event *ev)
{
switch (ev->type) {
case Expose : win1_on_expose (ev); break;
case KeyPress : win1_on_key_press (ev); break;
}
}
int main (int argc, char *argv[])
{
char *filename = "images/tux2.gif";
App_data a;
if (argc-1 != 1)
fprintf (stderr, "Usage: %s image\n", argv[0]);
else filename = argv[1];
if (ez_init() < 0) exit (1);
app_data_init (&a, filename);
a.win1 = ez_window_create ( /* Taille la fenetre pour l'image */
a.image1->width, a.image1->height,
filename, win1_event);
ez_set_data (a.win1, &a);
ez_window_dbuf(a.win1, 1);
ez_main_loop ();
app_data_destroy (&a);
exit(0);
}
|
This window is obtained:
To compile this file demo-13.c on Unix, type:
gcc -Wall demo-13.c ez-draw.c ez-image.c -o demo-13 -lX11 -lXext -L/usr/X11R6/lib -lm
or on Windows, type:
gcc -Wall demo-13.c ez-draw.c ez-image.c -o demo-13.exe -lgdi32 -lmsimg32 -lm
You can also append the executable file name at the end of EXECS_IM = in the Makefile on Unix, or in Makefile.win on Windows; then type make all to compile.
The formats PNG, GIF and BMP allow to store a transparency level, in what is called the alpha channel. The formats GIF and BMP store the alpha channel over 1 bit; the pixels are either transparent (0), or opaque (255). The PNG format stores the alpha channel over 8 bits (from 0 for transparent, to 255 for opaque).
The module ez-image is able to display an image by taking in account the transparency, using an opacity threshold on the alpha channel: the pixels are either opaques (displayed) or transparents (not displayed).
The next example demo-14.c gets two file names as arguments of the command line, then superimpose both images. You can move the second image using arrow keys, or change the opacity threshold using keys + and -.
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 | #include "ez-draw.h"
#include "ez-image.h"
typedef struct {
int i2_x, i2_y;
Ez_image *image1, *image2;
Ez_window win1;
} App_data;
void app_data_init (App_data *a, char *filename1, char *filename2)
{
a->image1 = ez_image_load (filename1);
if (a->image1 == NULL) exit (1);
a->image2 = ez_image_load (filename2);
if (a->image2 == NULL) exit (1);
/* Position initiale centre'e */
a->i2_x = (a->image1->width - a->image2->width ) / 2;
a->i2_y = (a->image1->height - a->image2->height) / 2;
}
void app_data_destroy (App_data *a)
{
ez_image_destroy (a->image1);
ez_image_destroy (a->image2);
}
void win1_on_expose (Ez_event *ev)
{
App_data *a = ez_get_data (ev->win);
ez_image_paint (a->win1, a->image1, 0, 0);
ez_image_paint (a->win1, a->image2, a->i2_x, a->i2_y);
ez_draw_text (a->win1, EZ_BLF, 10, a->image1->height+15,
"[Fleches] pour deplacer");
ez_draw_text (a->win1, EZ_BRF, a->image1->width-10, a->image1->height+15,
"Opacite [+-] : %d", a->image2->opacity);
}
void win1_on_key_press (Ez_event *ev)
{
App_data *a = ez_get_data (ev->win);
switch (ev->key_sym) {
case XK_q : ez_quit (); break;
case XK_Left :
case XK_KP_Left : a->i2_x-- ; break;
case XK_Right :
case XK_KP_Right : a->i2_x++ ; break;
case XK_Up :
case XK_KP_Up : a->i2_y-- ; break;
case XK_Down :
case XK_KP_Down : a->i2_y++ ; break;
case XK_minus :
case XK_KP_Subtract : a->image2->opacity--; break;
case XK_plus :
case XK_KP_Add : a->image2->opacity++; break;
default : return;
}
ez_send_expose (a->win1);
}
void win1_event (Ez_event *ev)
{
switch (ev->type) {
case Expose : win1_on_expose (ev); break;
case KeyPress : win1_on_key_press (ev); break;
}
}
int main (int argc, char *argv[])
{
char *file1 = "images/paper1.jpg", *file2 = "images/tux1.png";
App_data a;
if (argc-1 != 2)
fprintf (stderr, "Usage: %s image1 image2\n", argv[0]);
else { file1 = argv[1]; file2 = argv[2]; }
if (ez_init() < 0) exit(1);
app_data_init (&a, file1, file2);
a.win1 = ez_window_create (a.image1->width, a.image1->height+15,
"Demo 14 : images avec transparence", win1_event);
ez_set_data (a.win1, &a);
ez_window_dbuf(a.win1, 1);
ez_main_loop ();
app_data_destroy (&a);
exit(0);
}
|
This window is obtained:
It is also possible to create an image in memory, then set the pixels colors. The example demo-12.c displays the HSV palette computed in this manner.
This window is obtained:
You will find more informations about images in the Reference manual.