/* Auxiliary function - look for frame that's currently loading. */ static void update_currently_loaded_frame (FrameData* frame) { int tmp_count; if (gdk_pixbuf_animation_iter_on_currently_loading_frame(frame->iter)) return; /* frame is currently being loaded */ /* clear old content of pixbuf */ if (frame->pixbuf) g_object_unref (frame->pixbuf); frame->pixbuf = NULL; tmp_count = 0; do { int delay_time; if (++tmp_count > MAX_NUMBER_FRAMES) { /* protection against frames repeating */ return; } delay_time = gdk_pixbuf_animation_iter_get_delay_time (frame->iter); if (delay_time < 0) { /* this is last frame in the animation */ return; } g_time_val_add (&frame->time, delay_time * 1000); gdk_pixbuf_animation_iter_advance (frame->iter, &frame->time); } while (!gdk_pixbuf_animation_iter_on_currently_loading_frame (frame->iter)); /* store current content of the frame */ frame->pixbuf = gdk_pixbuf_copy (gdk_pixbuf_animation_iter_get_pixbuf (frame->iter)); }
static GdkPixbuf * _gdk_pixbuf_new_from_uri_at_scale (const char *uri, gint size, GError **error) { gboolean result; guchar buffer[LOAD_BUFFER_SIZE]; gssize bytes_read; GdkPixbufLoader *loader = NULL; GdkPixbuf *pixbuf; GdkPixbufAnimation *animation; GdkPixbufAnimationIter *iter; gboolean has_frame; SizePrepareContext info; GFile *file; GInputStream *input_stream; g_return_val_if_fail (uri != NULL, NULL); file = g_file_new_for_uri (uri); input_stream = G_INPUT_STREAM (g_file_read (file, NULL, error)); if (input_stream == NULL) { g_object_unref (file); return NULL; } has_frame = FALSE; result = FALSE; while (!has_frame) { bytes_read = g_input_stream_read (input_stream, buffer, sizeof (buffer), NULL, error); if (bytes_read == -1) { break; } result = TRUE; if (bytes_read == 0) { break; } if (loader == NULL) { loader = create_loader (file, buffer, bytes_read); if (1 <= size) { info.size = size; info.input_width = info.input_height = 0; g_signal_connect (loader, "size-prepared", G_CALLBACK (size_prepared_cb), &info); } g_assert (loader != NULL); } if (!gdk_pixbuf_loader_write (loader, (unsigned char *)buffer, bytes_read, error)) { result = FALSE; break; } animation = gdk_pixbuf_loader_get_animation (loader); if (animation) { iter = gdk_pixbuf_animation_get_iter (animation, NULL); if (!gdk_pixbuf_animation_iter_on_currently_loading_frame (iter)) { has_frame = TRUE; } g_object_unref (iter); } } if (loader == NULL) { /* This can happen if the above loop was exited due to the * g_input_stream_read() call failing. */ result = FALSE; } else if (*error != NULL) { gdk_pixbuf_loader_close (loader, NULL); result = FALSE; } else if (gdk_pixbuf_loader_close (loader, error) == FALSE) { if (!g_error_matches (*error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INCOMPLETE_ANIMATION)) result = FALSE; else g_clear_error (error); } if (!result) { g_clear_object (&loader); g_input_stream_close (input_stream, NULL, NULL); g_object_unref (input_stream); g_object_unref (file); return NULL; } g_input_stream_close (input_stream, NULL, NULL); g_object_unref (input_stream); g_object_unref (file); pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); if (pixbuf != NULL) { g_object_ref (G_OBJECT (pixbuf)); g_object_set_data (G_OBJECT (pixbuf), "gnome-original-width", GINT_TO_POINTER (info.input_width)); g_object_set_data (G_OBJECT (pixbuf), "gnome-original-height", GINT_TO_POINTER (info.input_height)); } g_object_unref (G_OBJECT (loader)); return pixbuf; }
/** * gnome_gdk_pixbuf_new_from_uri: * @uri: the uri of an image * @width: The width the image should have or -1 to not constrain the width * @height: The height the image should have or -1 to not constrain the height * @preserve_aspect_ratio: %TRUE to preserve the image's aspect ratio * * Loads a GdkPixbuf from the image file @uri points to, scaling it to the * desired size. If you pass -1 for @width or @height then the value * specified in the file will be used. * * When preserving aspect ratio, if both height and width are set the size * is picked such that the scaled image fits in a width * height rectangle. * * Return value: The loaded pixbuf, or NULL on error * * Since: 2.14 **/ GdkPixbuf * gnome_gdk_pixbuf_new_from_uri_at_scale (const char *uri, gint width, gint height, gboolean preserve_aspect_ratio) { GnomeVFSResult result; char buffer[LOAD_BUFFER_SIZE]; GnomeVFSFileSize bytes_read; GdkPixbufLoader *loader; GdkPixbuf *pixbuf; GdkPixbufAnimation *animation; GdkPixbufAnimationIter *iter; gboolean has_frame; SizePrepareContext info; GFile *file; GFileInputStream *file_input_stream; g_return_val_if_fail (uri != NULL, NULL); file = g_file_new_for_uri (uri); file_input_stream = g_file_read (file, NULL, NULL); if (file_input_stream == NULL) { g_object_unref (file); return NULL; } loader = gdk_pixbuf_loader_new (); if (1 <= width || 1 <= height) { info.width = width; info.height = height; info.input_width = info.input_height = 0; info.preserve_aspect_ratio = preserve_aspect_ratio; g_signal_connect (loader, "size-prepared", G_CALLBACK (size_prepared_cb), &info); } has_frame = FALSE; result = GNOME_VFS_ERROR_GENERIC; while (!has_frame) { bytes_read = g_input_stream_read (G_INPUT_STREAM (file_input_stream), buffer, sizeof (buffer), NULL, NULL); if (bytes_read == -1) { break; } result = GNOME_VFS_OK; if (bytes_read == 0) { break; } if (!gdk_pixbuf_loader_write (loader, (unsigned char *)buffer, bytes_read, NULL)) { result = GNOME_VFS_ERROR_WRONG_FORMAT; break; } animation = gdk_pixbuf_loader_get_animation (loader); if (animation) { iter = gdk_pixbuf_animation_get_iter (animation, NULL); if (!gdk_pixbuf_animation_iter_on_currently_loading_frame (iter)) { has_frame = TRUE; } g_object_unref (iter); } } gdk_pixbuf_loader_close (loader, NULL); if (result != GNOME_VFS_OK) { g_object_unref (G_OBJECT (loader)); g_input_stream_close (G_INPUT_STREAM (file_input_stream), NULL, NULL); g_object_unref (file_input_stream); g_object_unref (file); return NULL; } g_input_stream_close (G_INPUT_STREAM (file_input_stream), NULL, NULL); g_object_unref (file_input_stream); g_object_unref (file); pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); if (pixbuf != NULL) { g_object_ref (G_OBJECT (pixbuf)); g_object_set_data (G_OBJECT (pixbuf), "gnome-original-width", GINT_TO_POINTER (info.input_width)); g_object_set_data (G_OBJECT (pixbuf), "gnome-original-height", GINT_TO_POINTER (info.input_height)); } g_object_unref (G_OBJECT (loader)); return pixbuf; }
static VALUE rg_on_currently_loading_frame_p(VALUE self) { return CBOOL2RVAL(gdk_pixbuf_animation_iter_on_currently_loading_frame(RVAL2ITR(self))); }