diff options
Diffstat (limited to 'src/imagestore.c')
-rw-r--r-- | src/imagestore.c | 369 |
1 files changed, 0 insertions, 369 deletions
diff --git a/src/imagestore.c b/src/imagestore.c deleted file mode 100644 index 61ebcfb..0000000 --- a/src/imagestore.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - * imagestore.c - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <libgen.h> -#include <cairo.h> -#include <glib.h> -#include <gio/gio.h> -#include <gdk/gdk.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -#include "imagestore.h" -#include "utils.h" - -#define MAX_SIZES (32) - -struct image_record -{ - char *filename; - cairo_surface_t *surf[MAX_SIZES]; - int w[MAX_SIZES]; - int last_used[MAX_SIZES]; - int n_sizes; - int h_last_used; - int full_width; - int full_height; -}; - - -struct _imagestore -{ - int n_images; - struct image_record *images; - int max_images; - GFile *pparent; - GFile *iparent; - const char *storename; -}; - - -static int alloc_images(ImageStore *is, int new_max_images) -{ - struct image_record *images_new; - - images_new = realloc(is->images, - sizeof(struct image_record)*new_max_images); - if ( images_new == NULL ) return 1; - - is->images = images_new; - is->max_images = new_max_images; - return 0; -} - - -ImageStore *imagestore_new(const char *storename) -{ - ImageStore *is; - - is = calloc(1, sizeof(ImageStore)); - if ( is == NULL ) return NULL; - - is->images = NULL; - is->pparent = NULL; - if ( storename != NULL ) { - is->iparent = g_file_new_for_uri(storename); - } else { - is->iparent = NULL; - } - is->n_images = 0; - is->max_images = 0; - if ( alloc_images(is, 32) ) { - free(is); - return NULL; - } - - return is; -} - - -void imagestore_set_parent(ImageStore *is, GFile *parent) -{ - if ( is->pparent != NULL ) { - g_object_unref(is->pparent); - } - is->pparent = parent; -} - - -void imagestore_destroy(ImageStore *is) -{ - int i; - - for ( i=0; i<is->n_images; i++ ) { - int j; - free(is->images[i].filename); - for ( j=0; j<is->images[i].n_sizes; j++ ) { - if ( is->images[i].surf[j] != NULL ) { - g_object_unref(is->images[i].surf[j]); - } - } - } - g_object_unref(is->pparent); - g_object_unref(is->iparent); - free(is->images); - free(is); -} - - -static cairo_surface_t *pixbuf_to_surface(GdkPixbuf *t) -{ - cairo_surface_t *surf; - cairo_t *cr; - int w, h; - - if ( t == NULL ) return NULL; - - w = gdk_pixbuf_get_width(t); - h = gdk_pixbuf_get_height(t); - - surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); - if ( surf == NULL ) return NULL; - - cr = cairo_create(surf); - - gdk_cairo_set_source_pixbuf(cr, t, 0, 0); - cairo_pattern_t *patt = cairo_get_source(cr); - cairo_pattern_set_extend(patt, CAIRO_EXTEND_PAD); - cairo_pattern_set_filter(patt, CAIRO_FILTER_BEST); - cairo_paint(cr); - - cairo_destroy(cr); - - return surf; -} - - -static int try_load(GFile *file, GdkPixbuf **pixbuf, gint w, gint h) -{ - GFileInputStream *stream; - GError *error = NULL; - - stream = g_file_read(file, NULL, &error); - if ( stream != NULL ) { - GError *pberr = NULL; - *pixbuf = gdk_pixbuf_new_from_stream_at_scale(G_INPUT_STREAM(stream), - w, h, TRUE, - NULL, &pberr); - g_object_unref(stream); - g_object_unref(file); - return 1; - } - - return 0; -} - - -static GdkPixbuf *load_image(const char *uri, GFile *pparent, GFile *iparent, - gint w, gint h) -{ - GFile *file; - GdkPixbuf *pixbuf; - - /* Literal pathname */ - file = g_file_new_for_path(uri); - if ( try_load(file, &pixbuf, w, h) ) return pixbuf; - - /* Try the file prefixed with the directory the presentation is in */ - if ( pparent != NULL ) { - file = g_file_get_child(pparent, uri); - if ( try_load(file, &pixbuf, w, h) ) return pixbuf; - } - - /* Try prefixing with imagestore folder */ - if ( iparent != NULL ) { - file = g_file_get_child(iparent, uri); - if ( try_load(file, &pixbuf, w, h) ) return pixbuf; - } - - return NULL; -} - - -static struct image_record *add_image_record(ImageStore *is, - const char *filename) -{ - int idx; - - if ( is->n_images == is->max_images ) { - if ( alloc_images(is, is->max_images+32) ) { - fprintf(stderr, "Couldn't allocate memory for image " - "records.\n"); - return NULL; - } - } - - idx = is->n_images++; - - is->images[idx].n_sizes = 0; - is->images[idx].filename = strdup(filename); - is->images[idx].h_last_used = 0; - - return &is->images[idx]; -} - - - -int imagestore_get_size(ImageStore *is, const char *filename, - int *w, int *h) -{ - GdkPixbuf *pixbuf; - struct image_record *ir; - int i; - - for ( i=0; i<is->n_images; i++ ) { - if ( strcmp(is->images[i].filename, filename) == 0 ) { - *w = is->images[i].full_width; - *h = is->images[i].full_height; - return 0; - } - } - - pixbuf = load_image(filename, is->pparent, is->iparent, -1, -1); - if ( pixbuf == NULL ) return 1; - - - *w = gdk_pixbuf_get_width(pixbuf); - *h = gdk_pixbuf_get_height(pixbuf); - - ir = add_image_record(is, filename); - if ( ir != NULL ) { - ir->full_width = *w; - ir->full_height = *h; - } /* otherwise can't cache, too bad */ - - g_object_unref(pixbuf); - - return 0; -} - - -static int find_earliest(struct image_record *im) -{ - int i, earliest, l; - - earliest = im->h_last_used; - l = im->n_sizes; - - for ( i=0; i<im->n_sizes; i++ ) { - if ( im->last_used[i] < earliest ) { - earliest = im->last_used[i]; - l = i; - } - } - - assert(l != im->n_sizes); - - cairo_surface_destroy(im->surf[l]); - - return l; -} - - -static cairo_surface_t *add_image_size(struct image_record *im, - const char *filename, - GFile *pparent, GFile *iparent, - int w) -{ - cairo_surface_t *surf; - GdkPixbuf *t; - int pos; - - t = load_image(filename, pparent, iparent, w, -1); - if ( t == NULL ) return NULL; - surf = pixbuf_to_surface(t); - g_object_unref(t); - - /* Add surface to list */ - if ( im->n_sizes == MAX_SIZES ) { - pos = find_earliest(im); - } else { - pos = im->n_sizes++; - } - - im->w[pos] = w; - im->surf[pos] = surf; - im->last_used[pos] = im->h_last_used++; - - return surf; -} - - -static cairo_surface_t *add_new_image(ImageStore *is, const char *filename, int w) -{ - struct image_record *ir; - ir = add_image_record(is, filename); - if ( ir == NULL ) return NULL; - return add_image_size(ir, filename, is->pparent, is->iparent, w); -} - - -void show_imagestore(ImageStore *is) -{ - int i; - - printf("Store %p contains %i records.\n", is, is->n_images); - - for ( i=0; i<is->n_images; i++ ) { - - printf("%s :\n", is->images[i].filename); - printf("\n"); - - } -} - - -cairo_surface_t *lookup_image(ImageStore *is, const char *filename, int w) -{ - int i, j; - int found = 0; - cairo_surface_t *surf; - - for ( i=0; i<is->n_images; i++ ) { - if ( strcmp(is->images[i].filename, filename) == 0 ) { - found = 1; - break; - } - } - if ( !found ) { - return add_new_image(is, filename, w); - } - - for ( j=0; j<is->images[i].n_sizes; j++ ) { - if ( is->images[i].w[j] == w ) { - is->images[i].last_used[j] = is->images[i].h_last_used++; - return is->images[i].surf[j]; - } - } - - /* We don't have this size yet */ - surf = add_image_size(&is->images[i], filename, is->pparent, - is->iparent, w); - return surf; -} |