I've tried to execute a C program. And it has compiled right however when I execute the output binary, it displays:
[16] 70041 illegal hardware instruction ./create
So, I add -g option to look like this:
cc create.c $(pkg-config --cflags --libs cairo) -g -o create
And the C code:
#include <cairo.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(void){
cairo_surface_t *surface;
cairo_t *cr;
int j=0;
char seq[5];
for(int i=0; i<=360; i+=4){
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 800, 600);
cr = cairo_create(surface);
cairo_set_line_width (cr, 6.0);
cairo_arc( cr, 800/2, 600/2, (600/2)-50, 0, 2*M_PI );
cairo_stroke (cr);
cairo_set_source_rgb( cr, 0.2, 0.2, i/360 );
cairo_arc( cr, 800/2, 600/2, (600/2)-60, 0, i*(M_PI/180.0) );
cairo_stroke(cr);
j++;
if( j<10 ){ sprintf(seq, "%s%d%d", "seq", 0, j); } else { sprintf(seq, "%s%d", "seq", j); }
cairo_surface_write_to_png(surface, seq);
cairo_surface_destroy(surface);
}
cairo_destroy(cr);
return 0;
}
The purpose of above code is create a sequence of pngs pictures. But there isn't any warning at the output.
I include the lldb output:
(lldb) target create "create"
Current executable set to '/Users/rikky/Documents/C/Cairo/FirstDraw/create' (x86_64).
(lldb) l
7 int main(void){
8 cairo_surface_t *surface;
9 cairo_t *cr;
10 int j=0;
11 char seq[5];
12
13 for(int i=0; i<=360; i+=4){
14 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 800, 600);
15 cr = cairo_create(surface);
16 cairo_set_line_width (cr, 6.0);
(lldb) run
Process 70245 launched: '/Users/rikky/Documents/C/Cairo/FirstDraw/create' (x86_64)
Process 70245 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
frame #0: 0x00007fff6e80ffca libsystem_c.dylib`__chk_fail_overflow.cold.1 + 16
libsystem_c.dylib`__chk_fail_overflow.cold.1:
-> 0x7fff6e80ffca <+16>: ud2
libsystem_c.dylib`__chk_fail_overlap.cold.1:
0x7fff6e80ffcc <+0>: pushq %rbp
0x7fff6e80ffcd <+1>: movq %rsp, %rbp
0x7fff6e80ffd0 <+4>: leaq 0x6e41(%rip), %rdi ; "detected source and destination buffer overlap"
Target 0: (create) stopped.
I didn't understand the EXC_I386_INVOP code. Is there any way to fix it?
The Clang Version:
Apple clang version 12.0.0 (clang-1200.0.32.2)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Related
I'm trying to find an example of showing an image in GTK 4.0 from an existing memory buffer, where the image is stored in the form of an array of floats of size width x height x 3. I understand I need to use GtkImage, but I don't know how to pass such an array to it.
Just for context, I wanted to implement a prototype for rendering some images, they are all rendered in memory, and as a result, I have an array of such floats, three floats for each pixel. Unfortunately, I could not find any examples for the latest GTK 4.0. There are plenty of examples of loading an image from the disk, but it seems like jumping unnecessary hoops for my case. I used to load these as OpenGL texture and show them on a quad, but it also seems like driving nails with a sledgehammer.
Thank you in advance for any help!
You can use GdkMemoryTexture for an image in memory and use a GtkPicture and set the texture using gtk_picture_set_paintable() to paint it. The following is an example that creates an opaque 8bit RGB image and displays it on the screen:
/* pixel.c
*
* Compile: cc -ggdb pixel.c -o pixel $(pkg-config --cflags --libs gtk4) -o pixel
* Run: ./pixel
*
* Author: Mohammed Sadiq <www.sadiqpk.org>
*
* SPDX-License-Identifier: LGPL-2.1-or-later OR CC0-1.0
*/
#include <gtk/gtk.h>
#define BYTES_PER_R8G8B8 3
#define WIDTH 400
static void
fill_row (GByteArray *array,
guint8 value,
int row_size)
{
guint i;
for (i = 0; i < row_size; i++) {
/* Fill the same values for RGB */
g_byte_array_append (array, &value, 1); /* R */
g_byte_array_append (array, &value, 1); /* G */
g_byte_array_append (array, &value, 1); /* B */
}
}
static void
add_pixel_picture (GtkPicture *picture)
{
g_autoptr(GBytes) bytes = NULL;
GdkTexture *texture;
GByteArray *pixels;
gsize height;
/* Draw something interesting */
pixels = g_byte_array_new ();
for (guint i = 0; i <= 0xff ; i++)
fill_row (pixels, i, WIDTH);
for (guint i = 0; i <= 0xff; i++)
fill_row (pixels, 0xff - i, WIDTH);
height = pixels->len / (WIDTH * BYTES_PER_R8G8B8);
bytes = g_byte_array_free_to_bytes (pixels);
texture = gdk_memory_texture_new (WIDTH, height,
GDK_MEMORY_R8G8B8,
bytes,
WIDTH * BYTES_PER_R8G8B8);
gtk_picture_set_paintable (picture, GDK_PAINTABLE (texture));
}
static void
app_activated_cb (GtkApplication *app)
{
GtkWindow *window;
GtkWidget *picture;
window = GTK_WINDOW (gtk_application_window_new (app));
g_object_set (window,
"width-request", 500,
"height-request", 400,
NULL);
picture = gtk_picture_new ();
gtk_widget_add_css_class (picture, "frame");
g_object_set (picture,
"margin-start", 96,
"margin-end", 96,
"margin-top", 96,
"margin-bottom", 96,
NULL);
gtk_window_set_child (window, picture);
add_pixel_picture (GTK_PICTURE (picture));
gtk_window_present (window);
}
int
main (int argc,
char *argv[])
{
g_autoptr(GtkApplication) app = gtk_application_new (NULL, 0);
g_signal_connect (app, "activate", G_CALLBACK (app_activated_cb), NULL);
return g_application_run (G_APPLICATION (app), argc, argv);
}
Use the GdkMemoryFormat that suites your data, or convert it to one that's supported.
I'm using Kubuntu 18.04
So i recently tried to use SDL2, i wanted to create a simple window showing a few pictures following a tutorial but i was unable to compile the example code.
When i try to compile the code i get:
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libSDL2_image.so: undefined reference to `SDL_ceilf'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libSDL2_image.so: undefined reference to `SDL_acosf'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libSDL2_image.so: undefined reference to `SDL_floorf'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libSDL2_image.so: undefined reference to `SDL_fabsf'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libSDL2_image.so: undefined reference to `SDL_LoadFile_RW'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libSDL2_image.so: undefined reference to `SDL_fmodf'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libSDL2_image.so: undefined reference to `SDL_atan2f'
collect2: error: ld returned 1 exit status
Command used:
gcc SDLProject.c -o SDLProject `sdl2-config --cflags --libs` -lSDL2_gfx -lSDL2_image
Command used to install SDL2 libs:
sudo apt install libsdl2-dev libsdl2-gfx-dev libsdl2-image-dev libsdl2-ttf-dev libsdl2-mixer-dev
Installed packages:
sudo apt list --installed | grep "sdl"
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
libsdl2-2.0-0/bionic-updates,now 2.0.8+dfsg1-1ubuntu1.18.04.3 amd64 [installed]
libsdl2-dev/bionic-updates,now 2.0.8+dfsg1-1ubuntu1.18.04.3 amd64 [installed]
libsdl2-gfx-1.0-0/bionic,now 1.0.4+dfsg-1 amd64 [installed,automatic]
libsdl2-gfx-dev/bionic,now 1.0.4+dfsg-1 amd64 [installed]
libsdl2-image-2.0-0/bionic,now 2.0.3+dfsg1-1 amd64 [installed,automatic]
libsdl2-image-dev/bionic,now 2.0.3+dfsg1-1 amd64 [installed]
libsdl2-mixer-2.0-0/bionic,now 2.0.2+dfsg1-2 amd64 [installed,automatic]
libsdl2-mixer-dev/bionic,now 2.0.2+dfsg1-2 amd64 [installed]
libsdl2-ttf-2.0-0/bionic,now 2.0.14+dfsg1-2 amd64 [installed,automatic]
libsdl2-ttf-dev/bionic,now 2.0.14+dfsg1-2 amd64 [installed]
I already tried deleting everything that is related to SDL / SDL2 and only reinstalling the ones the project uses (SDL2, gfx and image) and i found out that this error only happens when i try to inlude the SDL_image.h and I'm able to run other exmaple codes that does not use it.
I do not think that the error is related to the code itself but:
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL2_gfxPrimitives.h>
#include <stdlib.h>
typedef enum Babu {
VKiraly, VVezer, VBastya, VFuto, VHuszar, VGyalog,
SKiraly, SVezer, SSastya, SFuto, SHuszar, SGyalog
} Babu;
enum { MERET = 52 };
void babu_rajzol(SDL_Renderer *renderer, SDL_Texture *babuk, Babu melyik, int x, int y) {
SDL_Rect src = { (melyik % 6) * 62 + 10, (melyik / 6) * 60 + 10, MERET, MERET };
SDL_Rect dest = { x, y, MERET, MERET };
SDL_RenderCopy(renderer, babuk, &src, &dest);
}
void sdl_init(int szeles, int magas, SDL_Window **pwindow, SDL_Renderer **prenderer) {
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
SDL_Log("Nem indithato az SDL: %s", SDL_GetError());
exit(1);
}
SDL_Window *window = SDL_CreateWindow("SDL peldaprogram", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, szeles, magas, 0);
if (window == NULL) {
SDL_Log("Nem hozhato letre az ablak: %s", SDL_GetError());
exit(1);
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE);
if (renderer == NULL) {
SDL_Log("Nem hozhato letre a megjelenito: %s", SDL_GetError());
exit(1);
}
SDL_RenderClear(renderer);
*pwindow = window;
*prenderer = renderer;
}
int main(int argc, char *argv[]) {
SDL_Window *window;
SDL_Renderer *renderer;
sdl_init(320, 200, &window, &renderer);
SDL_Texture *babuk = IMG_LoadTexture(renderer, "pieces.png");
if (babuk == NULL) {
SDL_Log("Nem nyithato meg a kepfajl: %s", IMG_GetError());
exit(1);
}
boxRGBA(renderer, 0, 0, 319, 199, 0x90, 0xE0, 0x90, 0xFF);
babu_rajzol(renderer, babuk, VKiraly, 82, 74);
babu_rajzol(renderer, babuk, SGyalog, 82+MERET, 74);
babu_rajzol(renderer, babuk, VHuszar, 82+2*MERET, 74);
SDL_RenderPresent(renderer);
SDL_DestroyTexture(babuk);
SDL_Event event;
while (SDL_WaitEvent(&event) && event.type != SDL_QUIT) {
}
SDL_Quit();
return 0;
}
You did not get the sdl package which contains sdl-config. You can get it from
sudo apt install libsdl1.2-dev
I have the following C code (for clarity, I know it's not complete code and it should handle events and stuff like that):
#!/usr/bin/tcc -run -L/usr/lib/x86_64-linux-gnu -D_REENTRANT -DSDL_MAIN_HANDLED -I/usr/include/SDL2 -lSDL2 -lGL -lGLEW
#include <GL/glew.h>
#include <SDL.h>
int main(int argc, char **argv)
{
SDL_Init(SDL_INIT_VIDEO);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_Window *win = SDL_CreateWindow("Hello World!", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
SDL_GLContext glContext = SDL_GL_CreateContext(win);
while (1)
{
glClearColor(1, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(win);
}
SDL_GL_DeleteContext(glContext);
SDL_DestroyWindow(win);
return 0;
}
If I compile this with GCC (without the shebang line), and start the executable, it works fine, but I like the simplicity of the compile and run functionality of TCC and its speed.
However, the compiled executable gives me the following console output and then hangs forever and can't even be killed with CTRL-C:
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
I added the SDL_MAIN_HANDLED as suggested here but that didn't change anything.
Anyone?
How about proper handling of the possible errors of the SDL calls and also initializing glew?
#include <stdlib.h>
#include <SDL.h>
#include <GL/glew.h>
void exit_sdl_error(const char *message) {
SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "%s failed with SDL error %s", message, SDL_GetError());
exit(EXIT_FAILURE);
}
int main() {
const Uint32 init_flags = SDL_INIT_VIDEO;
const int gl_major = 4, gl_minor = 0;
if (!SDL_WasInit(init_flags)) {
if (SDL_Init(init_flags) != 0)
exit_sdl_error("Unable to initialize SDL");
if (SDL_InitSubSystem(init_flags) != 0)
exit_sdl_error("Unable to initialize sub system of SDL");
}
if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, gl_major))
exit_sdl_error("Unable to set gl major version");
if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, gl_minor))
exit_sdl_error("Unable to set gl minor version");
if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE))
exit_sdl_error("Unable to set gl profile");
SDL_Window *window = SDL_CreateWindow("Hello World!", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (!window) {
SDL_QuitSubSystem(init_flags);
exit_sdl_error("Unable to create window");
}
SDL_GLContext glContext = SDL_GL_CreateContext(window);
if (!glContext) {
SDL_DestroyWindow(window);
SDL_QuitSubSystem(init_flags);
exit_sdl_error("Unable to create context");
}
glewInit();
while (1)
{
glClearColor(1, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(window);
}
SDL_GL_DeleteContext(glContext);
SDL_DestroyWindow(window);
SDL_QuitSubSystem(init_flags);
}
I'm trying to use the Cairo graphics library on Linux in C to make a pretty lightweight x11 GUI.
After trying very hard to follow the woefully incomplete guide that cairo gives for x11, this is the best I've got:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <cairo.h>
#include <cairo-xlib.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/renderproto.h>
//This function should give us a new x11 surface to draw on.
cairo_surface_t* create_x11_surface(int x, int y)
{
Display* d;
Drawable da;
int screen;
cairo_surface_t* sfc;
if((d = XOpenDisplay(NULL)) == NULL)
{
printf("failed to open display\n");
exit(1);
}
screen = DefaultScreen(d);
da = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, x, y, 0, 0, 0);
XSelectInput(d, da, ButtonPressMask | KeyPressMask);
XMapWindow(d, da);
sfc = cairo_xlib_surface_create(d, da, DefaultVisual(d, screen), x, y);
cairo_xlib_surface_set_size(sfc, x, y);
return sfc;
}
int main(int argc, char** argv)
{
//create a new cairo surface in an x11 window as well as a cairo_t* to draw
//on the x11 window with.
cairo_surface_t* surface = create_x11_surface(300, 200);
cairo_t* cr = cairo_create(surface);
while(1)
{
//save the empty drawing for the next time through the loop.
cairo_push_group(cr);
//draw some text
cairo_select_font_face(cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size(cr, 32.0);
cairo_set_source_rgb(cr, 0, 0, 1.0);
cairo_move_to(cr, 10.0, 25.0);
if((argc == 2) && (strnlen(argv[1], 100) < 50))
cairo_show_text(cr, argv[1]);
else
cairo_show_text(cr, "usage: ./p1 <string>");
//put the drawn text onto the screen(?)
cairo_pop_group_to_source(cr);
cairo_paint(cr);
cairo_surface_flush(surface);
//pause for a little bit.
int c = getchar();
//change the text around so we can see the screen update.
for(int i = 0; i < strnlen(argv[1], 100); i++)
{
argv[1][i] = argv[1][i + 1];
}
if(c == 'q')
{
break;
}
}
cairo_surface_destroy(surface);
return 0;
}
On Linux systems that have Cairo installed, it can be compiled with
gcc -o myprog $(pkg-config --cflags --libs cairo x11) -std=gnu99 main.c
And it should be run with a single argument.
For reasons I don't understand at all, inserting the line
cairo_pop_group_to_source(cr);
cairo_paint(cr);
cairo_surface_write_to_png (surface, "hello.png"); //<--------- inserted
cairo_surface_flush(surface);
Puts something on the screen, but there are 2 problems:
Text that I draw with this method is persistent, creating a smearing effect.
I don't want some .png file mediating between my program and an x11 window. Data should be sent directly!
Several issues:
In X11, the X11 server doesn't save what you drew to a window, but instead sends an ExposeEvent to your window that tells it to redraw. This means you get a black window, because you do not handle this event.
getchar only gives you something after a line break, so just typing something won't help.
libX11 buffers stuff and only sends it to the X11 server when you wait for an event (or the buffer fills up). Since you never wait for an event, it never flushes. Calling XFlush explicitly helps.
The group that you push is useless. Just get rid of it.
Your code to move the string one direction to the left easily goes beyond the end of the string. You apparently know this already, because you 'fixed' this with a strnlen.
Here is a little better solution, but it still gives you an initially black window, because you draw to it before it is mapped:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <cairo-xlib.h>
#include <X11/Xlib.h>
//This function should give us a new x11 surface to draw on.
cairo_surface_t* create_x11_surface(Display *d, int x, int y)
{
Drawable da;
int screen;
cairo_surface_t* sfc;
screen = DefaultScreen(d);
da = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, x, y, 0, 0, 0);
XSelectInput(d, da, ButtonPressMask | KeyPressMask);
XMapWindow(d, da);
sfc = cairo_xlib_surface_create(d, da, DefaultVisual(d, screen), x, y);
return sfc;
}
int main(int argc, char** argv)
{
Display *d = XOpenDisplay(NULL);
if (d == NULL) {
fprintf(stderr, "Failed to open display\n");
return 1;
}
//create a new cairo surface in an x11 window as well as a cairo_t* to draw
//on the x11 window with.
cairo_surface_t* surface = create_x11_surface(d, 300, 200);
cairo_t* cr = cairo_create(surface);
char *text = argv[1];
size_t text_len = 0;
if (argc != 2)
text = NULL;
else
text_len = strlen(text);
while(1)
{
// Clear the background
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_paint(cr);
//draw some text
cairo_select_font_face(cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size(cr, 32.0);
cairo_set_source_rgb(cr, 0, 0, 1.0);
cairo_move_to(cr, 10.0, 25.0);
if (text)
cairo_show_text(cr, text);
else
cairo_show_text(cr, "usage: ./p1 <string>");
cairo_surface_flush(surface);
XFlush(d);
//pause for a little bit.
int c = getchar();
//change the text around so we can see the screen update.
memmove(text, &text[1], text_len);
if (text_len > 0)
text_len--;
printf("got char %c\n", c);
if(c == 'q')
{
break;
}
}
// XXX: Lots of other stuff isn't properly destroyed here
cairo_surface_destroy(surface);
return 0;
}
Edit: Also, why exactly do you feel like cairo only gives you a woefully incomplete guide? It tells you how to get the cairo parts working and it also explains you some parts about X11, even though you should already know those if you want to use cairo-x11. That's none of its business. The guide you linked to even provides a complete, working and self-contained example: https://www.cypherpunk.at/files/2014/11/cairo_xlib_simple.c
I've you would have read the complete text of this "imcomplete guide" you would have seen that there is a link to the full sample: https://www.cypherpunk.at/files/2014/11/cairo_xlib_simple.c .
I've got a simple Cairo program that attempts to draw a diagonal consisting of dots in a 600x600 PNG. However, the output appears to be truncated whenever I attempt to render all of the dots using a single call to cairo_stroke().
Specifically, consider the following program:
#include <cairo/cairo.h>
int main(int argc, char **argv)
{
cairo_surface_t *surface =
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 300, 300);
cairo_t *cr = cairo_create(surface);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_set_line_width(cr, 5);
for (double x = 0.0; x <= 300; x += 10) {
cairo_move_to(cr, x, x);
cairo_close_path(cr);
cairo_stroke(cr);
}
cairo_surface_write_to_png(surface, "output.png");
cairo_destroy(cr);
cairo_surface_destroy(surface);
return 0;
}
which generates the following correct output:
If I move the
cairo_stroke(cr);
outside of the for loop, then the following incorrect output is generated instead:
.
Can someone else explain why the second attempt fails? I suspect I must be doing something wrong here...
#include <cairo/cairo.h>
int main(int argc, char **argv)
{
cairo_surface_t *surface =
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 300, 300);
cairo_t *cr = cairo_create(surface);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_set_line_width(cr, 5);
for (double x = 0.0; x <= 300; x += 10) {
cairo_move_to(cr, x, x);
cairo_close_path(cr);
}
cairo_stroke(cr); /* moved here */
cairo_surface_write_to_png(surface, "output.png");
cairo_destroy(cr);
cairo_surface_destroy(surface);
return 0;
}
Moving cairo_stroke(cr) outside the for-loop seems to generate equal output with Cairo version 1.10.1.
Compiled as: gcc test.c `pkg-config --libs --cflags gtk+-2.0` -std=c99 -lcairo