Do produce thumbnails of thumbnails, but in memory
This commit is contained in:
parent
ae0b5506ab
commit
4e11970a7e
|
@ -729,17 +729,6 @@ thumbnailers_start(FivBrowser *self)
|
||||||
if (!self->model)
|
if (!self->model)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO(p): Leave out all paths containing .cache/thumbnails altogether.
|
|
||||||
gchar *thumbnails_dir = fiv_thumbnail_get_root();
|
|
||||||
GFile *thumbnails = g_file_new_for_path(thumbnails_dir);
|
|
||||||
g_free(thumbnails_dir);
|
|
||||||
|
|
||||||
GFile *current = fiv_io_model_get_location(self->model);
|
|
||||||
gboolean is_a_thumbnail = current && g_file_has_prefix(current, thumbnails);
|
|
||||||
g_object_unref(thumbnails);
|
|
||||||
if (is_a_thumbnail)
|
|
||||||
return;
|
|
||||||
|
|
||||||
GList *missing = NULL, *lq = NULL;
|
GList *missing = NULL, *lq = NULL;
|
||||||
for (guint i = self->entries->len; i--; ) {
|
for (guint i = self->entries->len; i--; ) {
|
||||||
Entry *entry = &g_array_index(self->entries, Entry, i);
|
Entry *entry = &g_array_index(self->entries, Entry, i);
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "fiv-io.h"
|
#include "fiv-io.h"
|
||||||
#include "fiv-thumbnail.h"
|
#include "fiv-thumbnail.h"
|
||||||
|
@ -93,7 +94,7 @@ mark_thumbnail_lq(cairo_surface_t *surface)
|
||||||
surface, &fiv_thumbnail_key_lq, (void *) (intptr_t) 1, NULL);
|
surface, &fiv_thumbnail_key_lq, (void *) (intptr_t) 1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *
|
static gchar *
|
||||||
fiv_thumbnail_get_root(void)
|
fiv_thumbnail_get_root(void)
|
||||||
{
|
{
|
||||||
gchar *cache_dir = get_xdg_home_dir("XDG_CACHE_HOME", ".cache");
|
gchar *cache_dir = get_xdg_home_dir("XDG_CACHE_HOME", ".cache");
|
||||||
|
@ -102,6 +103,23 @@ fiv_thumbnail_get_root(void)
|
||||||
return thumbnails_dir;
|
return thumbnails_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
might_be_a_thumbnail(const char *path_or_uri)
|
||||||
|
{
|
||||||
|
// It is generally difficult to discern case in/sensitivity of subpaths,
|
||||||
|
// so err on the side of false positives.
|
||||||
|
gchar *normalized = g_ascii_strdown(path_or_uri, -1);
|
||||||
|
|
||||||
|
// The Windows path separator must be percent-encoded in URIs,
|
||||||
|
// and the file scheme always uses forward slashes.
|
||||||
|
if (G_DIR_SEPARATOR != '/')
|
||||||
|
g_strdelimit(normalized, G_DIR_SEPARATOR_S, '/');
|
||||||
|
|
||||||
|
gboolean matches = strstr(normalized, "/.cache/thumbnails/") != NULL;
|
||||||
|
g_free(normalized);
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
static cairo_surface_t *
|
static cairo_surface_t *
|
||||||
|
@ -440,8 +458,10 @@ fiv_thumbnail_produce(GFile *target, FivThumbnailSize max_size, GError **error)
|
||||||
g_return_val_if_fail(max_size >= FIV_THUMBNAIL_SIZE_MIN &&
|
g_return_val_if_fail(max_size >= FIV_THUMBNAIL_SIZE_MIN &&
|
||||||
max_size <= FIV_THUMBNAIL_SIZE_MAX, FALSE);
|
max_size <= FIV_THUMBNAIL_SIZE_MAX, FALSE);
|
||||||
|
|
||||||
|
// Don't save thumbnails for FUSE mounts, such as sftp://.
|
||||||
|
// Moreover, it doesn't make sense to save thumbnails of thumbnails.
|
||||||
const gchar *path = g_file_peek_path(target);
|
const gchar *path = g_file_peek_path(target);
|
||||||
if (!path || !g_file_is_native(target) /* Don't save sftp://. */)
|
if (!path || !g_file_is_native(target) || might_be_a_thumbnail(path))
|
||||||
return produce_fallback(target, max_size, error);
|
return produce_fallback(target, max_size, error);
|
||||||
|
|
||||||
// Make the TOCTTOU issue favour unnecessary reloading.
|
// Make the TOCTTOU issue favour unnecessary reloading.
|
||||||
|
@ -620,6 +640,11 @@ fiv_thumbnail_lookup(const char *uri, gint64 mtime_msec, FivThumbnailSize size)
|
||||||
g_return_val_if_fail(size >= FIV_THUMBNAIL_SIZE_MIN &&
|
g_return_val_if_fail(size >= FIV_THUMBNAIL_SIZE_MIN &&
|
||||||
size <= FIV_THUMBNAIL_SIZE_MAX, NULL);
|
size <= FIV_THUMBNAIL_SIZE_MAX, NULL);
|
||||||
|
|
||||||
|
// Don't waste time looking up something that shouldn't exist--
|
||||||
|
// thumbnail directories tend to get huge, and syscalls are expensive.
|
||||||
|
if (might_be_a_thumbnail(uri))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
gchar *sum = g_compute_checksum_for_string(G_CHECKSUM_MD5, uri, -1);
|
gchar *sum = g_compute_checksum_for_string(G_CHECKSUM_MD5, uri, -1);
|
||||||
gchar *thumbnails_dir = fiv_thumbnail_get_root();
|
gchar *thumbnails_dir = fiv_thumbnail_get_root();
|
||||||
|
|
||||||
|
|
|
@ -52,9 +52,6 @@ extern FivThumbnailSizeInfo fiv_thumbnail_sizes[FIV_THUMBNAIL_SIZE_COUNT];
|
||||||
/// If non-NULL, indicates a thumbnail of insufficient quality.
|
/// If non-NULL, indicates a thumbnail of insufficient quality.
|
||||||
extern cairo_user_data_key_t fiv_thumbnail_key_lq;
|
extern cairo_user_data_key_t fiv_thumbnail_key_lq;
|
||||||
|
|
||||||
/// Returns this user's root thumbnail directory.
|
|
||||||
gchar *fiv_thumbnail_get_root(void);
|
|
||||||
|
|
||||||
/// Attempts to extract any low-quality thumbnail from fast targets.
|
/// Attempts to extract any low-quality thumbnail from fast targets.
|
||||||
/// If `max_size` is a valid value, the image will be downscaled as appropriate.
|
/// If `max_size` is a valid value, the image will be downscaled as appropriate.
|
||||||
cairo_surface_t *fiv_thumbnail_extract(
|
cairo_surface_t *fiv_thumbnail_extract(
|
||||||
|
|
Loading…
Reference in New Issue