2. Reference manual¶
Sources: ez-draw.h, ez-draw.c.
2.1. Main loop¶
-
int ez_init()¶
Initialization.
Return 0 on success, -1 on failure.
-
void ez_main_loop()¶
Main loop.
This function displays the existing windows, then waits for events; for each incoming event the function calls the corresponding window event function (the callback).
To stop the main loop, call ez_quit()
in a callback.
Once returned from ez_main_loop()
, no more graphic call should be done.
-
void ez_quit()¶
Exit
ez_main_loop()
.
-
void ez_auto_quit(int val)¶
Modify the effect of the “Close” button in the title bar of a window, for each window of the program.
By default (val = 1
), if you click on the “Close” button of any
window of the program, it ends immediately.
You can change this behavior by invoking ez_auto_quit()
with
val = 0
: then, if the user clicks on the “Close” button of a window,
the program (instead of ending) will receive the event
WindowClose
for this window, so as to decide what to do:
ignore the event;
destroy the window with
ez_window_destroy()
;hide the window with
ez_window_show()
;create a dialog window;
complete the program with
ez_quit()
;etc.
Note: when all windows are destroyed, the program stops.
2.2. Windows¶
Each window has a unique identifier, of type Ez_window
:
-
type Ez_window¶
Identifier of a window.
The following functions allow to create or manipulate windows:
-
Ez_window ez_window_create(int w, int h, const char *name, Ez_func on_event)¶
Create and display a window, having width
w
and heighth
, a titlename
, and a functionon_event
(the callback) called for each event (on_event
might beNULL
).Return the identifier of the window, of type
Ez_window
.
Any callback has type Ez_func
:
-
type Ez_func¶
The type of a callback, that is to say, the prototype of an event handler, the function called for each event. This type is defined as:
typedef void (*Ez_func)(Ez_event *ev);
In other words, the function
on_event
given toez_create_window()
has to be declared as:void on_event (Ez_event *ev);
2.3. Events¶
Each event is described by a struct of type Ez_event
:
-
type Ez_event¶
Store an event.
This type is defined in ez-draw.h as follows:
typedef struct {
int type; /* Expose, ButtonPress, etc */
Ez_window win; /* Identifier of the window */
int mx, my; /* Mouse coordinates */
int mb; /* Mouse button, 0 = none */
int width, height; /* Width and height */
KeySym key_sym; /* Key symbol: XK_Space, XK_q, etc */
char key_name[80]; /* For tracing: "XK_Space", "XK_q", .. */
char key_string[80]; /* Corresponding string: " ", "q", etc */
int key_count; /* String length */
/* Other fields private */
} Ez_event;
The first field gives the event type. The possible values are:
|
The whole window must be redrawn. |
|
Mouse button pressed. |
|
Mouse button released. |
|
Mouse moved. |
|
Key pressed. |
|
Key released. |
|
The window size has changed. |
|
The button “Close” was pressed. |
|
The timer has expired. |
2.4. Colors¶
Each color is denoted by an integer of type Ez_uint32
.
-
void ez_set_color(Ez_uint32 color)¶
Store the color
color
for the next drawings, as well as for text displaying.
The following colors are predefined:
ez_black
, ez_white
, ez_grey
, ez_red
, ez_green
, ez_blue
,
ez_yellow
, ez_cyan
, ez_magenta
.
Other colors can be obtained with these functions:
-
Ez_uint32 ez_get_RGB(Ez_uint8 r, Ez_uint8 g, Ez_uint8 b)¶
Return a color computed according to the levels
r,g,b
given between 0 and 255.
-
Ez_uint32 ez_get_grey(Ez_uint8 g)¶
Return a grey color computed according to the level
g
given between 0 and 255.
-
Ez_uint32 ez_get_HSV(double h, double s, double v)¶
Return a color defined in space Hue, Saturation, Value.
h
is an angle between 0 and 360 degrees which arbitrary represents pure colors;
s
is saturation, between 0 and 1 ; v
is the luminosity value,
between 0 and 1.
For more information, see
Hue Saturation Value
in Wikipedia.
-
void ez_HSV_to_RGB(double h, double s, double v, Ez_uint8 *r, Ez_uint8 *g, Ez_uint8 *b)¶
Convert a color from HSV to RGB.
The ranges are:
h
between 0 and 360,s
andv
between 0 and 1,*r
,*g
,*b
between 0 and 255.
As examples, see demo-11.c and demo-12.c.
These windows are obtained:
2.5. Drawings¶
The coordinates are relative to the Origin, which is the top left point
inside the window; x
goes to the right and y
goes down.
For rectangles and circles, x1,y1
and y2,y2
are the top left and
bottom right coordinates of the bounding box.
For points, line segments and triangles, the vertex coordinates are
expected.
The default color is black; it can be changed with ez_set_color()
.
-
void ez_draw_triangle(Ez_window win, int x1, int y1, int x2, int y2, int x3, int y3)¶
Draw a triangle.
-
void ez_fill_triangle(Ez_window win, int x1, int y1, int x2, int y2, int x3, int y3)¶
Fill a triangle.
Drawings with ez_draw_point()
, ez_draw_line()
,
ez_draw_rectangle()
, ez_draw_triangle()
, ez_draw_circle()
have a default thickness of 1 pixel. It can be changed with:
-
void ez_set_thick(int thick)¶
Set thickness
thick
(in pixels) for the next drawings.
2.6. Text and fonts¶
-
int ez_font_load(int num, const char *name)¶
Load the font
name
(e.g."6x13"
) and store it as the font numbernum
.Return 0 on success, -1 on error.
The font number must be less than EZ_FONT_MAX
.
Some fixed fonts are preloaded by default:
Font number 0:
"6x13"
Font number 1:
"8x16"
Font number 2:
"10x20"
Font number 3:
"12x24"
- Note:
On X11, the name can be in any fashion but must correspond to an existing font. On Windows, the name must be in the form width
x
height (a matching font of fixed size is obtained).
-
void ez_set_nfont(int num)¶
Set the font number
num
for the next text drawings.
-
void ez_draw_text(Ez_window win, Ez_Align align, int x1, int y1, const char *format, ...)¶
Display text; same usage as
printf
.
Example:
ez_draw_text (win, EZ_TL, 10, 10, "Width = %d\nHeight = %d", w, h);
The coordinates x1,y1
are relative to align
,
which takes for values:
|
|
|
|
|
|
|
|
|
The text is drawn over the current content of the window; you can also delete
the background at the same time (with white) using these values for align
:
|
|
|
|
|
|
|
|
|
- By default:
the text is displayed using font number 0 (
6x13
); it can be changed byez_set_nfont()
.the text is displayed in black; the color can be changed with
ez_set_color()
.
2.7. Double buffering¶
Displaying with a double buffer prevents the window flashes while it is refreshed. The idea is to draw in the double buffer, then swap it with the window content when all the drawings are finished. Everything is handled automatically by EZ-Draw.
-
void ez_window_dbuf(Ez_window win, int val)¶
Enable or disable the double buffer display for the window
win
.
By default, the double buffering is disabled (val = 0
).
If the double buffering is enabled (val = 1
) for a window,
every drawings in this window must be made during Expose
events only.
If the double buffering is disabled, it is no longer a requirement,
but it is strongly advised.
As an example, see in game jeu-nim.c the functions
gui_init()
, win1_onKeyPress()
, win1_onExpose()
.
In this game, you can test the display with or without the double buffer
(press key d
to switch between one and the other):
2.8. Timers¶
Starting a timer means storing a date in the future, which is the current date plus a certain delay. When we arrive at this date in the future, we say that the timer has expired.
Each window can be associated with a timer.
Upon expiration of the timer, the program receives a unique event
TimerNotify
for the window, then the timer is deleted.
-
void ez_start_timer(Ez_window win, int delay)¶
Start a timer for the window
win
with the delaydelay
expressed in milliseconds.
Any recall of this function before timer expiration will cancel and replace
the timer with the new delay. Moreover, if delay
is -1
then the timer
is deleted.
(Note: this is not an error to delete a timer already deleted or non-existent).
An an example, see demo-09.c.
2.9. Client-data¶
Each window can store an arbitrary data of the program, for instance a string or a struct address. You can then recover the data at any time in the program. This mechanism aims to avoid global variables.
Here is an example of program that draws a circle, whose coordinates
are stored into a global variable md
:
1#include "ez-draw.h"
2
3typedef struct {
4 int x, y, r;
5} My_data;
6
7My_data md; /* 1. Global variable */
8
9
10void win1_on_expose (Ez_event *ev)
11{
12 /* 3. Use */
13 ez_draw_circle (ev->win, md.x-md.r, md.y-md.r, md.x+md.r, md.y+md.r);
14}
15
16
17void win1_on_event (Ez_event *ev)
18{
19 switch (ev->type) {
20 case Expose : win1_on_expose (ev); break;
21 }
22}
23
24
25int main ()
26{
27 if (ez_init() < 0) exit(1);
28
29 /* 2. Initialization */
30 md.x = 200; md.y = 100; md.r = 50;
31
32 ez_window_create (400, 300, "Demo client-data 1", win1_on_event);
33
34 ez_main_loop ();
35 exit(0);
36}
Here is now the same program but without using global variable; the data are stored in the window:
1#include "ez-draw.h"
2
3typedef struct {
4 int x, y, r;
5} My_data;
6
7
8void win1_on_expose (Ez_event *ev)
9{
10 /* 4. We retrieve the data stored in the window */
11 My_data *md = ez_get_data (ev->win);
12
13 /* 5. Use */
14 ez_draw_circle (ev->win, md->x-md->r, md->y-md->r, md->x+md->r, md->y+md->r);
15}
16
17
18void win1_on_event (Ez_event *ev)
19{
20 switch (ev->type) {
21 case Expose : win1_on_expose (ev); break;
22 }
23}
24
25
26int main ()
27{
28 Ez_window win1;
29 My_data md; /* 1. Local variable to main() */
30
31 if (ez_init() < 0) exit(1);
32
33 /* 2. Initialization */
34 md.x = 200; md.y = 100; md.r = 50;
35
36 win1 = ez_window_create (400, 300, "Demo client-data 2", win1_on_event);
37
38 /* 3. We store the data in the window */
39 ez_set_data (win1, &md);
40
41 ez_main_loop ();
42 exit(0);
43}
As another example, see demo-10.c.
2.10. The image type¶
EZ-Draw allows to display or to manipulate images, thanks to the type:
-
type Ez_image¶
Main
struct
type to store an image.
This type is defined in ez-image.h as follows:
typedef struct {
int width, height;
Ez_uint8 *pixels_rgba;
int has_alpha;
int opacity;
} Ez_image;
Guess what: the image width in pixels is width
and its height is height
.
The pixels are stored in the table pixels_rgba
as R,G,B,A (for red, green, blue and alpha, that is to say transparency)
each having a value between 0 and 255 (255 is the maximum intensity or opacity).
The R,G,B,A values of a pixel having coordinates x,y
in the image
are stored in pixels_rgba[(y*width+x)*4 + 0..3]
.
The has_alpha
field indicates if the alpha channel is used (has_alpha = 1
)
or ignored (has_alpha = 0
) when displaying.
If the channel is ignored, all pixels are displayed;
if used, just the opaque pixels are displayed.
The opaque pixels are those for which the alpha channel is greater or equal
to the opacity threshold, specified by the opacity
field;
by default, the opacity threshold is 128.
- Warning:
do not modified the fields
width
,height
,pixels_rgba
of an image, since they describe the allocated memory. However, you can change the fieldshas_alpha
,opacity
, as well as the pixel values inpixels_rgba[]
. You may also use the following functions.
2.11. Managing images¶
To use the following functions you must include ez-image.h.
-
Ez_image *ez_image_create(int w, int h)¶
Create an image having width
w
and heighth
, in pixels.Return the created image, or
NULL
on error.
-
Ez_image *ez_image_load(const char *filename)¶
Load an image from the file
filename
. The file must be in PNG, JPEG, GIF or BMP format.Transparency is supported for PNG, GIF and BMP format: if the file contains an alpha channel, then the field
has_alpha
of the image is set to 1.Return the created image, or
NULL
on error.
-
Ez_image *ez_image_dup(Ez_image *img)¶
Create a deep copy of the image
img
.Return the created image, or
NULL
on error.
-
void ez_image_destroy(Ez_image *img)¶
Destroy an image in memory.
All images created by
ez_image_...
should be destroyed using this function.
-
void ez_image_paint(Ez_window win, Ez_image *img, int x, int y)¶
Display an image in the window
win
, with the upper left corner of the image at thex,y
coordinates in the window. Ifimg->has_alpha
is true, apply transparency, that is to say, only display opaque pixels.
-
void ez_image_paint_sub(Ez_window win, Ez_image *img, int x, int y, int src_x, int src_y, int w, int h)¶
Display a rectangular region of an image in the window
win
.The image region is bounded by coordinates
src_x, src_y
(top left corner) andsrc_x+w-1, src_y+h-1
(bottom right corner) in the image. If the coordinates go beyond the image, just the region which actually fits in the image is displayed.The top left corner of the region is displayed at the
x,y
coordinate in the window. Ifimg->has_alpha
is true, apply transparency.
-
void ez_image_print(Ez_image *img, int src_x, int src_y, int w, int h)¶
Display a rectangular region of an image in the terminal.
The image region is bounded by coordinates
src_x, src_y
(top left corner) andsrc_x+w-1, src_y+h-1
(bottom right corner) in the image. If the coordinates go beyond the image, just the region which actually fits in the image is displayed.
2.12. Operations on images¶
This section presents some operations which are available by including ez-image.h. These operations are done on colors and on the alpha channel.
-
void ez_image_fill_rgba(Ez_image *img, Ez_uint8 r, Ez_uint8 g, Ez_uint8 b, Ez_uint8 a)¶
Fill an image with color
r,g,b,a
.The values are between 0 and 255.
-
void ez_image_blend(Ez_image *dst, Ez_image *src, int dst_x, int dst_y)¶
-
void ez_image_blend_sub(Ez_image *dst, Ez_image *src, int dst_x, int dst_y, int src_x, int src_y, int w, int h)¶
Superimpose a region of image
src
into the imagedst
.The region of source image
src
is bounded by coordinatessrc_x, src_y
(top left corner) andsrc_x+w-1, src_y+h-1
(bottom right corner). The function superimposes this region into the destination imagedst
at coordinatesdst_x, dst_y
(top left corner) anddst_x+w-1, dst_y+h-1
(bottom right corner).If the coordinates go beyond the images
src
ordst
, just the common region is superimposed. If the source image has no alpha channel (src->has_alpha
is false), then the pixel values from thesrc
region overwrite those ofdst
. Otherwise, the regions are melted by transparency (alpha blending) using formulas of Porter and Duff.
-
Ez_image *ez_image_extract(Ez_image *img, int src_x, int src_y, int w, int h)¶
Create an image containing a copy of a rectangular region of the source image
img
.The region of the image is bounded by coordinates
src_x, src_y
(top left corner) andsrc_x+w-1, src_y+h-1
(bottom right corner) inimg
. If the coordinates go beyond the image, just the region fitting in the image is extracted.Return
NULL
on memory error or if intersection is empty.
-
Ez_image *ez_image_sym_ver(Ez_image *img)¶
-
Ez_image *ez_image_sym_hor(Ez_image *img)¶
Create an image of same size and properties as the source image
img
, containing the symmetrical image with respect to the vertical or horizontal axis.Return the new image, or
NULL
on error.
-
Ez_image *ez_image_scale(Ez_image *img, double factor)¶
Create an image whose size is scaled by the
factor
with respect to the source imageimg
, containing the rescaled image. The scale factorfactor
must be strictly positive.Return the new image, or
NULL
on error.
-
Ez_image *ez_image_rotate(Ez_image *img, double theta, int quality)¶
Compute a rotation of the source image
img
for angletheta
, in degrees. Return a new image whose size is adjusted to contain the result, orNULL
on error.In the resulting image, the field
has_alpha
is set to 1, and the parts not coming from the source image are transparent, in such a manner that they will not appear when displaying.If
quality = 1
, the function smooths the result (with a bi-linear interpolation); ifquality = 0
, the function focuses on speed (using a closest neighbour computation), which saves a factor about 3.
- Note :
the result being independent from the rotation center, it is not required as a parameter; however you can separately choose a rotation center and compute its coordinates in the destination image, thanks to the following function:
-
void ez_image_rotate_point(Ez_image *img, double theta, int src_x, int src_y, int *dst_x, int *dst_y)¶
Compute for a point having coordinates
src_x,src_y
in the source image, the corresponding coordinatesdst_x,dst_y
of the point in the destination image.
The example demo-16.c illustrates rotations, with or without transparency. The rotation center (red cross) is movable with the arrow keys. You can even modify quality.
These windows are obtained:
2.13. Speed up image display¶
We have seen in the previous sections the type Ez_image
defined
in ez-image.h.
This type is convenient for loading, transforming and displaying images. However, displaying an image takes a few milliseconds to a few tens of milliseconds, this duration varying with the image size and computer power.
The reason is that for each display, ez_image_paint()
computes again
the whole conversion from the type Ez_image
, to an intermediate
image in memory, applies the transparency if needed, sends the result
to the graphic card, which finally displays it.
We can trace the duration of operations in the terminal, by setting an environment variable then running one of the demonstration programs: on Unix, type
export EZ_IMAGE_DEBUG=1
or on Windows, type:
set EZ_IMAGE_DEBUG=1
We obtain this for instance on 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
To cancel this environment variable on Unix, type:
unset EZ_IMAGE_DEBUG
or on Windows, type:
set EZ_IMAGE_DEBUG=
In an animation, all these times add up, and when there are a lot of images,
the animation may be jerky.
The solution is simple: convert the image of type Ez_image
as a pixmap of type Ez_pixmap
, then display the pixmap.
- typedef struct Ez_pixmap
A pixmap is an image already converted and stored in the graphic card. Its display is way faster, and also relieves the processor of the machine.
Once created, a pixmap is immutable.
This solution is also interesting to display a background image (which size is often large). In this case, we can also gain efficiency by using an image without alpha channel.
The type Ez_pixmap
is defined as:
typedef struct {
int width, height;
/* other fields private */
} Ez_pixmap
The following functions handle pixmaps:
-
Ez_pixmap *ez_pixmap_create_from_image(Ez_image *img)¶
Create a pixmap from an image
img
. The pixmap keeps the image transparency. The image can then be freed if no longer needed.Return the new pixmap, or
NULL
on error.
-
void ez_pixmap_destroy(Ez_pixmap *pix)¶
Delete the pixmap
pix
.All pixmaps must be freed by this function.
-
void ez_pixmap_paint(Ez_window win, Ez_pixmap *pix, int x, int y)¶
Display the pixmap
pix
in the windowwin
.The top left corner of the pixmap is displayed at the
x,y
coordinates in the window.
-
void ez_pixmap_tile(Ez_window win, Ez_pixmap *pix, int x, int y, int w, int h)¶
Display the pixmap
pix
repeatedly in the windowwin
.The pixmap is displayed as a wallpaper in the window region bounded by coordinates
x,y
(top left corner) andx+w-1,y+h-1
(bottom right corner).
The example demo-17.c allows to check the display speed, measured in fps
(frame per second) in an animation.
Use keys +
and -
to change the number of balls,
and key p
to enable or disable the use of pixmaps.
This window is obtained:
2.14. Miscellaneous¶
-
int ez_random(int n)¶
Return a random integer between 0 and
n-1
.
Note: the random generator is initialized by ez_init()
.
-
double ez_get_time()¶
Return the time elapsed since the Epoch (1970, january the 1st at 0:00:00) in seconds, with a precision in microseconds.
This function is usefull for measuring the duration of computations: just call
ez_get_time()
before and after the computation, and then display the
difference:
double t1, t2;
t1 = ez_get_time ();
my_computation ();
t2 = ez_get_time ();
printf ("Duration: %.6f s\n", t2-t1)