StTextureCache: add api to load image to cairo surface

Loading a pixbuf in a way that cairo can use it is a
pretty involved process that involves a lot of code, and pixel
fiddling.

This commit adds the mechanism to StTextureCache so we can reuse
the existing pixbuf handling code there, and also get caching.

https://bugzilla.gnome.org/show_bug.cgi?id=636976
This commit is contained in:
Ray Strode 2010-12-10 17:15:39 -05:00
parent a7fa7d748d
commit f7ab90b93b
2 changed files with 101 additions and 0 deletions

View File

@ -30,6 +30,7 @@
#define CACHE_PREFIX_GICON "gicon:"
#define CACHE_PREFIX_URI "uri:"
#define CACHE_PREFIX_URI_FOR_CAIRO "uri-for-cairo:"
#define CACHE_PREFIX_THUMBNAIL_URI "thumbnail-uri:"
#define CACHE_PREFIX_RAW_CHECKSUM "raw-checksum:"
#define CACHE_PREFIX_COMPRESSED_CHECKSUM "compressed-checksum:"
@ -798,6 +799,27 @@ pixbuf_to_cogl_handle (GdkPixbuf *pixbuf)
gdk_pixbuf_get_pixels (pixbuf));
}
static cairo_surface_t *
pixbuf_to_cairo_surface (GdkPixbuf *pixbuf)
{
cairo_surface_t *dummy_surface;
cairo_pattern_t *pattern;
cairo_surface_t *surface;
cairo_t *cr;
dummy_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
cr = cairo_create (dummy_surface);
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
pattern = cairo_get_source (cr);
cairo_pattern_get_surface (pattern, &surface);
cairo_surface_reference (surface);
cairo_destroy (cr);
cairo_surface_destroy (dummy_surface);
return surface;
}
static GdkPixbuf *
load_pixbuf_fallback(AsyncTextureLoadData *data)
{
@ -1504,6 +1526,45 @@ out:
return texdata;
}
static cairo_surface_t *
st_texture_cache_load_uri_sync_to_cairo_surface (StTextureCache *cache,
StTextureCachePolicy policy,
const gchar *uri,
int available_width,
int available_height,
GError **error)
{
cairo_surface_t *surface;
GdkPixbuf *pixbuf;
char *key;
key = g_strconcat (CACHE_PREFIX_URI_FOR_CAIRO, uri, NULL);
surface = g_hash_table_lookup (cache->priv->keyed_cache, key);
if (surface == NULL)
{
pixbuf = impl_load_pixbuf_file (uri, available_width, available_height, error);
if (!pixbuf)
goto out;
surface = pixbuf_to_cairo_surface (pixbuf);
g_object_unref (pixbuf);
if (policy == ST_TEXTURE_CACHE_POLICY_FOREVER)
{
cairo_surface_reference (surface);
g_hash_table_insert (cache->priv->keyed_cache, g_strdup (key), surface);
}
}
else
cairo_surface_reference (surface);
out:
g_free (key);
return surface;
}
/**
* st_texture_cache_load_uri_sync:
*
@ -1582,6 +1643,43 @@ st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
return texture;
}
/**
* st_texture_cache_load_file_to_cairo_surface:
* @cache: A #StTextureCache
* @file_path: Path to a file in supported image format
*
* This function synchronously loads the given file path
* into a cairo surface. On error, a warning is emitted
* and %NULL is returned.
*
* Returns: (transfer full): a new #cairo_surface_t *
*/
cairo_surface_t *
st_texture_cache_load_file_to_cairo_surface (StTextureCache *cache,
const gchar *file_path)
{
cairo_surface_t *surface;
GFile *file;
char *uri;
GError *error = NULL;
file = g_file_new_for_path (file_path);
uri = g_file_get_uri (file);
surface = st_texture_cache_load_uri_sync_to_cairo_surface (cache, ST_TEXTURE_CACHE_POLICY_FOREVER,
uri, -1, -1, &error);
g_object_unref (file);
g_free (uri);
if (surface == NULL)
{
g_warning ("Failed to load %s: %s", file_path, error->message);
g_clear_error (&error);
return NULL;
}
return surface;
}
/**
* st_texture_cache_load_file_simple:
* @cache: A #StTextureCache

View File

@ -119,6 +119,9 @@ ClutterActor *st_texture_cache_load_uri_sync (StTextureCache *cache,
CoglHandle st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
const gchar *file_path);
cairo_surface_t *st_texture_cache_load_file_to_cairo_surface (StTextureCache *cache,
const gchar *file_path);
ClutterActor *st_texture_cache_load_file_simple (StTextureCache *cache,
const gchar *file_path);