/** * Simple Evas example using the Buffer engine. * * You must have Evas compiled with the buffer engine, and have the * evas-software-buffer pkg-config files installed. * * @verbatim * gcc -o evas-buffer-simple evas-buffer-simple.c `pkg-config --libs --cflags evas evas-software-buffer` * @endverbatim */ #include #include #include #include #define WIDTH (320) #define HEIGHT (240) /* * create_canvas(), destroy_canvas() and draw_scene() are support functions. * * They are only required to use raw Evas, but for real world usage, * it is recommended to use ecore and its ecore-evas submodule, that * provide convenience canvas creators, integration with main loop and * automatic render of updates (draw_scene()) when system goes back to * main loop. */ static Evas *create_canvas(int width, int height); static void destroy_canvas(Evas *canvas); static void draw_scene(Evas *canvas); // support function to save scene as PPM image static void save_scene(Evas *canvas, const char *dest); int main(void) { Evas *canvas; Evas_Object *bg, *r1, *r2, *r3; evas_init(); // create your canvas // NOTE: consider using ecore_evas_buffer_new() instead! canvas = create_canvas(WIDTH, HEIGHT); if (!canvas) return -1; bg = evas_object_rectangle_add(canvas); evas_object_color_set(bg, 255, 255, 255, 255); // white bg evas_object_move(bg, 0, 0); // at origin evas_object_resize(bg, WIDTH, HEIGHT); // covers full canvas evas_object_show(bg); puts("initial scene, with just background:"); draw_scene(canvas); r1 = evas_object_rectangle_add(canvas); evas_object_color_set(r1, 255, 0, 0, 255); // 100% opaque red evas_object_move(r1, 10, 10); evas_object_resize(r1, 100, 100); evas_object_show(r1); // pay attention to transparency! Evas color values are pre-multiplied by // alpha, so 50% opaque green is: // non-premul: r=0, g=255, b=0 a=128 (50% alpha) // premul: // r_premul = r * a / 255 = 0 * 128 / 255 = 0 // g_premul = g * a / 255 = 255 * 128 / 255 = 128 // b_premul = b * a / 255 = 0 * 128 / 255 = 0 // // this 50% green is over a red background, so it will show in the // final output as yellow (green + red = yellow) r2 = evas_object_rectangle_add(canvas); evas_object_color_set(r2, 0, 128, 0, 128); // 50% opaque green evas_object_move(r2, 10, 10); evas_object_resize(r2, 50, 50); evas_object_show(r2); r3 = evas_object_rectangle_add(canvas); evas_object_color_set(r3, 0, 128, 0, 255); // 100% opaque dark green evas_object_move(r3, 60, 60); evas_object_resize(r3, 50, 50); evas_object_show(r3); puts("final scene (note updates):"); draw_scene(canvas); save_scene(canvas, "/tmp/evas-buffer-simple-render.ppm"); // NOTE: use ecore_evas_buffer_new() and here ecore_evas_free() destroy_canvas(canvas); evas_shutdown(); return 0; } static Evas *create_canvas(int width, int height) { Evas *canvas; Evas_Engine_Info_Buffer *einfo; int method; void *pixels; method = evas_render_method_lookup("buffer"); if (method <= 0) { fputs("ERROR: evas was not compiled with 'buffer' engine!\n", stderr); return NULL; } canvas = evas_new(); if (!canvas) { fputs("ERROR: could not instantiate new evas canvas.\n", stderr); return NULL; } evas_output_method_set(canvas, method); evas_output_size_set(canvas, width, height); evas_output_viewport_set(canvas, 0, 0, width, height); einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(canvas); if (!einfo) { fputs("ERROR: could not get evas engine info!\n", stderr); evas_free(canvas); return NULL; } // ARGB32 is sizeof(int), that is 4 bytes, per pixel pixels = malloc(width * height * sizeof(int)); if (!pixels) { fputs("ERROR: could not allocate canvas pixels!\n", stderr); evas_free(canvas); return NULL; } einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32; einfo->info.dest_buffer = pixels; einfo->info.dest_buffer_row_bytes = width * sizeof(int); einfo->info.use_color_key = 0; einfo->info.alpha_threshold = 0; einfo->info.func.new_update_region = NULL; einfo->info.func.free_update_region = NULL; evas_engine_info_set(canvas, (Evas_Engine_Info *)einfo); return canvas; } static void destroy_canvas(Evas *canvas) { Evas_Engine_Info_Buffer *einfo; einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(canvas); if (!einfo) { fputs("ERROR: could not get evas engine info!\n", stderr); evas_free(canvas); return; } free(einfo->info.dest_buffer); evas_free(canvas); } static void draw_scene(Evas *canvas) { Eina_List *updates, *n; Eina_Rectangle *update; // render and get the updated rectangles: updates = evas_render_updates(canvas); // informative only here, just print the updated areas: EINA_LIST_FOREACH(updates, n, update) printf("UPDATED REGION: pos: %3d, %3d size: %3dx%3d\n", update->x, update->y, update->w, update->h); // free list of updates evas_render_updates_free(updates); } static void save_scene(Evas *canvas, const char *dest) { Evas_Engine_Info_Buffer *einfo; const unsigned int *pixels, *pixels_end; int width, height; FILE *f; einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(canvas); if (!einfo) { fputs("ERROR: could not get evas engine info!\n", stderr); return; } evas_output_size_get(canvas, &width, &height); f = fopen(dest, "wb+"); if (!f) { fprintf(stderr, "ERROR: could not open for writing '%s': %s\n", dest, strerror(errno)); return; } pixels = einfo->info.dest_buffer; pixels_end = pixels + (width * height); // PPM P6 format is dead simple to write: fprintf(f, "P6\n%d %d\n255\n", width, height); for (; pixels < pixels_end; pixels++) { int r, g, b; r = ((*pixels) & 0xff0000) >> 16; g = ((*pixels) & 0x00ff00) >> 8; b = (*pixels) & 0x0000ff; fprintf(f, "%c%c%c", r, g, b); } fclose(f); printf("saved scene as '%s'\n", dest); }