diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c index c7906ab9c..52ce02ed0 100644 --- a/src/st/st-texture-cache.c +++ b/src/st/st-texture-cache.c @@ -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 diff --git a/src/st/st-texture-cache.h b/src/st/st-texture-cache.h index 4f1a4820a..5f1e70193 100644 --- a/src/st/st-texture-cache.h +++ b/src/st/st-texture-cache.h @@ -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);