diff options
Diffstat (limited to 'src/loader/loader.c')
| -rw-r--r-- | src/loader/loader.c | 58 |
1 files changed, 53 insertions, 5 deletions
diff --git a/src/loader/loader.c b/src/loader/loader.c index 9721c2a..65cc4cb 100644 --- a/src/loader/loader.c +++ b/src/loader/loader.c @@ -28,7 +28,6 @@ extern const GgazeLoaderBackend avif_backend; #ifdef HAVE_HEIF extern const GgazeLoaderBackend heif_backend; #endif - static const GgazeLoaderBackend *BACKENDS[] = { #ifdef HAVE_JXL &jxl_backend, @@ -70,7 +69,7 @@ loader_load(GFile *p_file, GCancellable *p_cancel, GError **p_err) { guint8 head[GGAZE_SNIFF_LEN]; gsize u_read = _read_header(p_file, p_cancel, head, GGAZE_SNIFF_LEN, p_err); - if (u_read == 0 && p_err != NULL && *p_err != NULL) { + if (u_read == 0 && p_err != NULL) { return (NULL); } @@ -87,12 +86,54 @@ loader_load(GFile *p_file, GCancellable *p_cancel, GError **p_err) { /* --- async wrapper (M3) -------------------------------------------------- */ +typedef struct { + LoaderProgressCb p_cb; + gpointer p_data; +} ProgressPair; + static void _load_task_thread(GTask *p_task, gpointer p_src, gpointer p_task_data, GCancellable *p_cancel) { - (void)p_task_data; - GError *p_err = NULL; - GdkTexture *p_tex = loader_load((GFile *)p_src, p_cancel, &p_err); + ProgressPair *p_pair = (ProgressPair *)p_task_data; + GError *p_err = NULL; + GdkTexture *p_tex = NULL; + + /* Sniff and dispatch to the first matching backend. */ + guint8 head[GGAZE_SNIFF_LEN]; + gsize u_read = + _read_header((GFile *)p_src, p_cancel, head, GGAZE_SNIFF_LEN, &p_err); + if (u_read == 0 && p_err != NULL) { + g_task_return_error(p_task, p_err); + return; + } + gboolean b_found = FALSE; +#ifdef HAVE_JPEG + extern const GgazeLoaderBackend jpeg_backend; + if (detect_format(head, u_read) == GGAZE_FMT_JPEG && p_pair != NULL) { + p_tex = jpeg_backend.load_progressive( + (GFile *)p_src, p_cancel, p_pair->p_cb, p_pair->p_data, &p_err); + b_found = TRUE; + } +#endif + if (!b_found) { + for (gsize u_i = 0; u_i < G_N_ELEMENTS(BACKENDS); u_i++) { + if (BACKENDS[u_i]->can_load(head, u_read)) { + if (BACKENDS[u_i]->load_progressive != NULL && p_pair != NULL) { + p_tex = BACKENDS[u_i]->load_progressive((GFile *)p_src, p_cancel, + p_pair->p_cb, + p_pair->p_data, &p_err); + } else { + p_tex = BACKENDS[u_i]->load((GFile *)p_src, p_cancel, &p_err); + } + b_found = TRUE; + break; + } + } + } /* end if (!b_found) */ + if (!b_found) { + g_set_error(&p_err, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "unsupported or unrecognized image format"); + } if (p_tex == NULL) { g_task_return_error(p_task, p_err); } else { @@ -102,9 +143,16 @@ _load_task_thread(GTask *p_task, gpointer p_src, gpointer p_task_data, void loader_load_async(GFile *p_file, GCancellable *p_cancel, + LoaderProgressCb p_progress, gpointer p_progress_data, GAsyncReadyCallback p_cb, gpointer p_data) { g_return_if_fail(G_IS_FILE(p_file)); GTask *p_task = g_task_new(p_file, p_cancel, p_cb, p_data); + if (p_progress != NULL) { + ProgressPair *p_pair = g_new(ProgressPair, 1); + p_pair->p_cb = p_progress; + p_pair->p_data = p_progress_data; + g_task_set_task_data(p_task, p_pair, (GDestroyNotify)g_free); + } g_task_run_in_thread(p_task, _load_task_thread); g_object_unref(p_task); } |
