diff options
Diffstat (limited to 'fastiv-io.c')
-rw-r--r-- | fastiv-io.c | 68 |
1 files changed, 45 insertions, 23 deletions
diff --git a/fastiv-io.c b/fastiv-io.c index 0e9b8c4..f9756f9 100644 --- a/fastiv-io.c +++ b/fastiv-io.c @@ -955,39 +955,58 @@ open_xcursor(const gchar *data, gsize len, GError **error) return NULL; } - // Let's just arrange the pixel data in a recording surface. - static cairo_user_data_key_t key = {}; - cairo_surface_t *recording = - cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA, NULL); - cairo_surface_set_user_data( - recording, &key, images, (cairo_destroy_func_t) XcursorImagesDestroy); - cairo_t *cr = cairo_create(recording); + // Interpret cursors as animated pages. + cairo_surface_t *pages = NULL, *frames_head = NULL, *frames_tail = NULL; - // Unpack horizontally by animation, vertically by size. + // XXX: Assuming that all "nominal sizes" have the same dimensions. XcursorDim last_nominal = -1; - int x = 0, y = 0, row_height = 0; for (int i = 0; i < images->nimage; i++) { XcursorImage *image = images->images[i]; - if (image->size != last_nominal) { - x = 0; - y += row_height; - row_height = 0; - last_nominal = image->size; - } // The library automatically byte swaps in _XcursorReadImage(). - cairo_surface_t *source = cairo_image_surface_create_for_data( + cairo_surface_t *surface = cairo_image_surface_create_for_data( (unsigned char *) image->pixels, CAIRO_FORMAT_ARGB32, image->width, image->height, image->width * sizeof *image->pixels); - cairo_set_source_surface(cr, source, x, y); - cairo_surface_destroy(source); - cairo_paint(cr); + cairo_surface_set_user_data(surface, &fastiv_io_key_frame_duration, + (void *) (intptr_t) image->delay, NULL); + + if (pages && image->size == last_nominal) { + cairo_surface_set_user_data(surface, + &fastiv_io_key_frame_previous, frames_tail, NULL); + cairo_surface_set_user_data(frames_tail, + &fastiv_io_key_frame_next, surface, + (cairo_destroy_func_t) cairo_surface_destroy); + } else if (frames_head) { + cairo_surface_set_user_data(frames_head, + &fastiv_io_key_frame_previous, frames_tail, NULL); + + cairo_surface_set_user_data(frames_head, + &fastiv_io_key_page_next, surface, + (cairo_destroy_func_t) cairo_surface_destroy); + cairo_surface_set_user_data(surface, + &fastiv_io_key_page_previous, frames_head, NULL); + frames_head = surface; + } else { + pages = frames_head = surface; + } - x += image->width; - row_height = MAX(row_height, (int) image->height); + frames_tail = surface; + last_nominal = image->size; } - cairo_destroy(cr); - return recording; + if (!pages) { + XcursorImagesDestroy(images); + return NULL; + } + + // Wrap around animations in the last page. + cairo_surface_set_user_data( + frames_head, &fastiv_io_key_frame_previous, frames_tail, NULL); + + // There is no need to copy data, assign it to the surface. + static cairo_user_data_key_t key = {}; + cairo_surface_set_user_data( + pages, &key, images, (cairo_destroy_func_t) XcursorImagesDestroy); + return pages; } #endif // HAVE_XCURSOR -------------------------------------------------------- @@ -1041,6 +1060,9 @@ cairo_user_data_key_t fastiv_io_key_frame_previous; cairo_user_data_key_t fastiv_io_key_frame_duration; cairo_user_data_key_t fastiv_io_key_loops; +cairo_user_data_key_t fastiv_io_key_page_next; +cairo_user_data_key_t fastiv_io_key_page_previous; + cairo_surface_t * fastiv_io_open(const gchar *path, GError **error) { |