Bug Summary

File:_build/../cdk-pixbuf/cdk-pixbuf-io.c
Warning:line 546, column 9
Potential leak of memory pointed to by 'module'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cdk-pixbuf-io.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/_build -fcoverage-compilation-dir=/rootdir/_build -resource-dir /usr/lib/llvm-21/lib/clang/21 -I cdk-pixbuf/libcdk_pixbuf-2.0.so.0.4500.0.p -I cdk-pixbuf -I ../cdk-pixbuf -I . -I .. -I cdk-pixbuf/pixops -I ../cdk-pixbuf/pixops -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/libmount -I /usr/include/blkid -D _FILE_OFFSET_BITS=64 -D _POSIX_C_SOURCE=200809L -D _DEFAULT_SOURCE -D _XOPEN_SOURCE=700 -D HAVE_CONFIG_H=1 -D G_LOG_STRUCTURED=1 -D G_LOG_DOMAIN="CdkPixbuf" -D CDK_PIXBUF_COMPILATION -D CDK_PIXBUF_PREFIX="/usr/local" -D CDK_PIXBUF_LOCALEDIR="/usr/local/share/locale" -D CDK_PIXBUF_LIBDIR="/usr/local/lib/x86_64-linux-gnu" -D CDK_PIXBUF_BINARY_VERSION="2.10.0" -D CDK_PIXBUF_ENABLE_BACKEND -D PIXBUF_LIBDIR="/usr/local/lib/x86_64-linux-gnu/cdk-pixbuf-2.0/2.10.0/loaders" -D BUILT_MODULES_DIR="/rootdir/_build/cdk-pixbuf" -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-int-conversion -Wno-uninitialized -Wno-discarded-qualifiers -std=gnu99 -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker security.ArrayBound -analyzer-checker unix.cstring.NotNullTerminated -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2026-06-05-101004-8567-1 -x c ../cdk-pixbuf/cdk-pixbuf-io.c
1/* CdkPixbuf library - Main loading interface.
2 *
3 * Copyright (C) 1999 The Free Software Foundation
4 *
5 * Authors: Miguel de Icaza <miguel@gnu.org>
6 * Federico Mena-Quintero <federico@gimp.org>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "config.h"
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27#include <errno(*__errno_location ()).h>
28#ifdef HAVE_UNISTD_H1
29#include <unistd.h>
30#endif
31
32#include <glib.h>
33#include <gio/gio.h>
34
35#include "cdk-pixbuf-private.h"
36#include "cdk-pixbuf-loader.h"
37#include "cdk-pixdata.h"
38
39#include <glib/gstdio.h>
40
41#ifdef G_OS_WIN32
42#define STRICT
43#include <windows.h>
44#undef STRICT
45#endif
46#ifdef OS_DARWIN
47#include <mach-o/dyld.h>
48#endif
49
50G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
51
52/**
53 * CdkPixbufModule:
54 * @module_name: the name of the module, usually the same as the
55 * usual file extension for images of this type, eg. "xpm", "jpeg" or "png".
56 * @module_path: the path from which the module is loaded.
57 * @module: the loaded `GModule`.
58 * @info: a `CdkPixbufFormat` holding information about the module.
59 * @load: loads an image from a file.
60 * @load_xpm_data: loads an image from data in memory.
61 * @begin_load: begins an incremental load.
62 * @stop_load: stops an incremental load.
63 * @load_increment: continues an incremental load.
64 * @load_animation: loads an animation from a file.
65 * @save: saves a `CdkPixbuf` to a file.
66 * @save_to_callback: saves a `CdkPixbuf` by calling the given `CdkPixbufSaveFunc`.
67 * @is_save_option_supported: returns whether a save option key is supported by the module
68 *
69 * A `CdkPixbufModule` contains the necessary functions to load and save
70 * images in a certain file format.
71 *
72 * If `CdkPixbuf` has been compiled with `GModule` support, it can be extended
73 * by modules which can load (and perhaps also save) new image and animation
74 * formats.
75 *
76 * ## Implementing modules
77 *
78 * The `CdkPixbuf` interfaces needed for implementing modules are contained in
79 * `cdk-pixbuf-io.h` (and `cdk-pixbuf-animation.h` if the module supports
80 * animations). They are not covered by the same stability guarantees as the
81 * regular CdkPixbuf API. To underline this fact, they are protected by the
82 * `CDK_PIXBUF_ENABLE_BACKEND` pre-processor symbol.
83 *
84 * Each loadable module must contain a `CdkPixbufModuleFillVtableFunc` function
85 * named `fill_vtable`, which will get called when the module
86 * is loaded and must set the function pointers of the `CdkPixbufModule`.
87 *
88 * In order to make format-checking work before actually loading the modules
89 * (which may require calling `dlopen` to load image libraries), modules export
90 * their signatures (and other information) via the `fill_info` function. An
91 * external utility, `cdk-pixbuf-query-loaders`, uses this to create a text
92 * file containing a list of all available loaders and their signatures.
93 * This file is then read at runtime by `CdkPixbuf` to obtain the list of
94 * available loaders and their signatures.
95 *
96 * Modules may only implement a subset of the functionality available via
97 * `CdkPixbufModule`. If a particular functionality is not implemented, the
98 * `fill_vtable` function will simply not set the corresponding
99 * function pointers of the `CdkPixbufModule` structure. If a module supports
100 * incremental loading (i.e. provides `begin_load`, `stop_load` and
101 * `load_increment`), it doesn't have to implement `load`, since `CdkPixbuf`
102 * can supply a generic `load` implementation wrapping the incremental loading.
103 *
104 * ## Installing modules
105 *
106 * Installing a module is a two-step process:
107 *
108 * - copy the module file(s) to the loader directory (normally
109 * `$libdir/cdk-pixbuf-2.0/$version/loaders`, unless overridden by the
110 * environment variable `CDK_PIXBUF_MODULEDIR`)
111 * - call `cdk-pixbuf-query-loaders` to update the module file (normally
112 * `$libdir/cdk-pixbuf-2.0/$version/loaders.cache`, unless overridden
113 * by the environment variable `CDK_PIXBUF_MODULE_FILE`)
114 */
115
116static gint
117format_check (CdkPixbufModule *module, guchar *buffer, int size)
118{
119 int i, j;
120 gchar m;
121 CdkPixbufModulePattern *pattern;
122 gboolean anchored;
123 guchar *prefix;
124 gchar *mask;
125
126 for (pattern = module->info->signature; pattern->prefix; pattern++) {
127 if (pattern->mask && pattern->mask[0] == '*') {
128 prefix = (guchar *)pattern->prefix + 1;
129 mask = pattern->mask + 1;
130 anchored = FALSE(0);
131 }
132 else {
133 prefix = (guchar *)pattern->prefix;
134 mask = pattern->mask;
135 anchored = TRUE(!(0));
136 }
137 for (i = 0; i < size; i++) {
138 for (j = 0; i + j < size && prefix[j] != 0; j++) {
139 m = mask ? mask[j] : ' ';
140 if (m == ' ') {
141 if (buffer[i + j] != prefix[j])
142 break;
143 }
144 else if (m == '!') {
145 if (buffer[i + j] == prefix[j])
146 break;
147 }
148 else if (m == 'z') {
149 if (buffer[i + j] != 0)
150 break;
151 }
152 else if (m == 'n') {
153 if (buffer[i + j] == 0)
154 break;
155 }
156 }
157
158 if (prefix[j] == 0)
159 return pattern->relevance;
160
161 if (anchored)
162 break;
163 }
164 }
165 return 0;
166}
167
168G_LOCK_DEFINE_STATIC (init_lock)static GMutex g__init_lock_lock;
169
170static gboolean file_formats_inited;
171static GSList *file_formats = NULL((void*)0);
172
173static gboolean cdk_pixbuf_io_init (void);
174
175static GSList *
176get_file_formats (void)
177{
178 G_LOCK (init_lock)g_mutex_lock (&g__init_lock_lock);
179 if (file_formats == NULL((void*)0) ||
11
Assuming 'file_formats' is equal to NULL
180 !file_formats_inited)
181 file_formats_inited = cdk_pixbuf_io_init ();
12
Calling 'cdk_pixbuf_io_init'
182 G_UNLOCK (init_lock)g_mutex_unlock (&g__init_lock_lock);
183
184 return file_formats;
185}
186
187#ifdef CDK_PIXBUF_RELOCATABLE // implies that cdk-pixbuf is built as a dll on windows
188
189#ifdef G_OS_WIN32
190
191/* DllMain function needed to tuck away the cdk-pixbuf DLL handle */
192
193static HMODULE cdk_pixbuf_dll;
194
195BOOL WINAPI
196DllMain (HINSTANCE hinstDLL,
197 DWORD fdwReason,
198 LPVOID lpvReserved)
199{
200 switch (fdwReason) {
201 case DLL_PROCESS_ATTACH:
202 cdk_pixbuf_dll = (HMODULE) hinstDLL;
203 break;
204 }
205
206 return TRUE(!(0));
207}
208#endif
209
210gchar *
211cdk_pixbuf_get_toplevel (void)
212{
213 static gchar *toplevel = NULL((void*)0);
214
215 if (toplevel == NULL((void*)0)) {
216#if defined(G_OS_WIN32)
217 toplevel = g_win32_get_package_installation_directory_of_module (cdk_pixbuf_dll);
218#elif defined(OS_DARWIN)
219 char pathbuf[PATH_MAX4096 + 1];
220 uint32_t bufsize = sizeof(pathbuf);
221 gchar *bin_dir;
222
223 _NSGetExecutablePath(pathbuf, &bufsize);
224 bin_dir = g_dirnameg_path_get_dirname GCC warning "Deprecated pre-processor symbol: replace with \"g_path_get_dirname\""
(pathbuf);
225 toplevel = g_build_path (G_DIR_SEPARATOR_S"/", bin_dir, "..", NULL((void*)0));
226 g_free (bin_dir);
227#elif defined (OS_LINUX1)
228 gchar *exe_path, *bin_dir;
229
230 exe_path = g_file_read_link ("/proc/self/exe", NULL((void*)0));
231 bin_dir = g_dirnameg_path_get_dirname GCC warning "Deprecated pre-processor symbol: replace with \"g_path_get_dirname\""
(exe_path);
232 toplevel = g_build_path (G_DIR_SEPARATOR_S"/", bin_dir, "..", NULL((void*)0));
233 g_free (exe_path);
234 g_free (bin_dir);
235#else
236#error "Relocations not supported for this platform"
237#endif
238 }
239 return toplevel;
240}
241
242#endif /* CDK_PIXBUF_RELOCATABLE */
243
244
245#ifdef USE_GMODULE
246
247static gboolean
248scan_string (const char **pos, GString *out)
249{
250 const char *p = *pos, *q = *pos;
251 char *tmp, *tmp2;
252 gboolean quoted;
253
254 while (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0))
255 p++;
256
257 if (!*p)
258 return FALSE(0);
259 else if (*p == '"') {
260 p++;
261 quoted = FALSE(0);
262 for (q = p; (*q != '"') || quoted; q++) {
263 if (!*q)
264 return FALSE(0);
265 quoted = (*q == '\\') && !quoted;
266 }
267
268 tmp = g_strndup (p, q - p);
269 tmp2 = g_strcompress (tmp);
270 g_string_truncate (out, 0)g_string_truncate_inline (out, 0);
271 g_string_append (out, tmp2)(__builtin_constant_p (tmp2) ? __extension__ ({ const char * const
__val = (tmp2); g_string_append_len_inline (out, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_88 = 0; if (__val != ((
void*)0)) _g_boolean_var_88 = 1; _g_boolean_var_88; }), 1)) ?
(gssize) strlen (((__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(out, tmp2, (gssize) -1))
;
272 g_free (tmp);
273 g_free (tmp2);
274 }
275
276 q++;
277 *pos = q;
278
279 return TRUE(!(0));
280}
281
282static gboolean
283scan_int (const char **pos, int *out)
284{
285 int i = 0;
286 char buf[32];
287 const char *p = *pos;
288
289 while (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0))
290 p++;
291
292 if (*p < '0' || *p > '9')
293 return FALSE(0);
294
295 while ((*p >= '0') && (*p <= '9') && i < sizeof (buf)) {
296 buf[i] = *p;
297 i++;
298 p++;
299 }
300
301 if (i == sizeof (buf))
302 return FALSE(0);
303 else
304 buf[i] = '\0';
305
306 *out = atoi (buf);
307
308 *pos = p;
309
310 return TRUE(!(0));
311}
312
313static gboolean
314skip_space (const char **pos)
315{
316 const char *p = *pos;
317
318 while (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0))
319 p++;
320
321 *pos = p;
322
323 return !(*p == '\0');
324}
325
326#ifdef CDK_PIXBUF_RELOCATABLE
327
328static char *
329get_libdir (void)
330{
331 static char *libdir = NULL((void*)0);
332
333 if (libdir == NULL((void*)0))
334 libdir = g_build_filename (cdk_pixbuf_get_toplevel (), "lib", NULL((void*)0));
335
336 return libdir;
337}
338
339#undef CDK_PIXBUF_LIBDIR"/usr/local/lib/x86_64-linux-gnu"
340#define CDK_PIXBUF_LIBDIR"/usr/local/lib/x86_64-linux-gnu" get_libdir()
341
342#endif /* CDK_PIXBUF_RELOCATABLE */
343
344/* In case we have a relative module path in the loaders cache
345 * prepend the toplevel dir */
346static gchar *
347build_module_path (const gchar *path)
348{
349#ifdef CDK_PIXBUF_RELOCATABLE
350 if (g_path_is_absolute (path)) {
351 return g_strdup (path)g_strdup_inline (path);
352 } else {
353 return g_build_filename (cdk_pixbuf_get_toplevel (), path, NULL((void*)0));
354 }
355#else
356 return g_strdup (path)g_strdup_inline (path);
357#endif
358}
359
360static gchar *
361cdk_pixbuf_get_module_file (void)
362{
363 gchar *result = g_strdup (g_getenv ("CDK_PIXBUF_MODULE_FILE"))g_strdup_inline (g_getenv ("CDK_PIXBUF_MODULE_FILE"));
364
365 if (!result)
366 result = g_build_filename (CDK_PIXBUF_LIBDIR"/usr/local/lib/x86_64-linux-gnu", "cdk-pixbuf-2.0", CDK_PIXBUF_BINARY_VERSION"2.10.0", "loaders.cache", NULL((void*)0));
367
368 return result;
369}
370
371#endif /* USE_GMODULE */
372
373
374static gboolean
375cdk_pixbuf_load_module_unlocked (CdkPixbufModule *image_module,
376 GError **error);
377
378static gboolean
379cdk_pixbuf_io_init_modules (const char *filename,
380 GError **error)
381{
382#ifdef USE_GMODULE
383 GIOChannel *channel;
384 gchar *line_buf;
385 gsize term;
386 GString *tmp_buf = g_string_new (NULL((void*)0));
387 gboolean have_error = FALSE(0);
388 CdkPixbufModule *module = NULL((void*)0);
389 int flags = 0;
390 int n_patterns = 0;
391 CdkPixbufModulePattern *pattern;
392 GError *local_error = NULL((void*)0);
393 guint num_formats;
394
395 channel = g_io_channel_new_file (filename, "r", &local_error);
396 if (!channel) {
14
Assuming 'channel' is non-null
15
Taking false branch
397 char *filename_utf8 = g_filename_display_name (filename);
398 g_set_error (error,
399 G_IO_ERRORg_io_error_quark(),
400 G_IO_ERROR_INVALID_ARGUMENT,
401 "Cannot open pixbuf loader module file '%s': %s\n\n"
402 "This likely means that your installation is broken.\n"
403 "Try running the command\n"
404 " cdk-pixbuf-query-loaders > %s\n"
405 "to make things work again for the time being.",
406 filename_utf8, local_error->message, filename_utf8);
407 g_clear_error (&local_error);
408 g_string_free (tmp_buf, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(tmp_buf), ((!(0)))) : g_string_free_and_steal (tmp_buf)) : (
g_string_free) ((tmp_buf), ((!(0)))))
;
409 g_free (filename_utf8);
410 return FALSE(0);
411 }
412
413 num_formats = g_slist_length (file_formats);
414
415 while (!have_error
15.1
'have_error' is 0
26.1
'have_error' is 0
&& g_io_channel_read_line (channel, &line_buf, NULL((void*)0), &term, NULL((void*)0)) == G_IO_STATUS_NORMAL) {
16
Assuming the condition is true
17
Loop condition is true. Entering loop body
27
Assuming the condition is false
28
Loop condition is false. Execution jumps to the end of the function
416 const char *p;
417
418 p = line_buf;
419
420 line_buf[term] = 0;
421
422 if (!skip_space (&p)) {
18
Assuming the condition is false
19
Taking false branch
423 /* Blank line marking the end of a module */
424 if (module && *p != '#') {
425 file_formats = g_slist_prepend (file_formats, module);
426 module = NULL((void*)0);
427 }
428
429 goto next_line;
430 }
431
432 if (*p == '#')
20
Assuming the condition is false
21
Taking false branch
433 goto next_line;
434
435 if (!module
21.1
'module' is null
) {
22
Taking true branch
436 /* Read a module location */
437 module = g_new0 (CdkPixbufModule, 1)(CdkPixbufModule *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (CdkPixbufModule); gpointer __p; if (__s
== 1) __p = g_malloc0 (__n); else if (__builtin_constant_p (
__n) && (__s == 0 || __n <= (9223372036854775807L *
2UL+1UL) / __s)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n
(__n, __s); __p; }))
;
23
Taking false branch
24
Memory is allocated
438 n_patterns = 0;
439
440 if (!scan_string (&p, tmp_buf)) {
25
Assuming the condition is false
26
Taking false branch
441 g_warning ("Error parsing loader info in '%s'\n %s",
442 filename, line_buf);
443 have_error = TRUE(!(0));
444 }
445 module->module_path = build_module_path (tmp_buf->str);
446 }
447 else if (!module->module_name) {
448 module->info = g_new0 (CdkPixbufFormat, 1)(CdkPixbufFormat *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (CdkPixbufFormat); gpointer __p; if (__s
== 1) __p = g_malloc0 (__n); else if (__builtin_constant_p (
__n) && (__s == 0 || __n <= (9223372036854775807L *
2UL+1UL) / __s)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n
(__n, __s); __p; }))
;
449 if (!scan_string (&p, tmp_buf)) {
450 g_warning ("Error parsing loader info in '%s'\n %s",
451 filename, line_buf);
452 have_error = TRUE(!(0));
453 }
454 module->info->name = g_strdup (tmp_buf->str)g_strdup_inline (tmp_buf->str);
455 module->module_name = module->info->name;
456
457 flags = 0;
458 if (!scan_int (&p, &flags)) {
459 g_warning ("Error parsing loader info in '%s'\n %s",
460 filename, line_buf);
461 have_error = TRUE(!(0));
462 }
463 module->info->flags = flags;
464
465 if (!scan_string (&p, tmp_buf)) {
466 g_warning ("Error parsing loader info in '%s'\n %s",
467 filename, line_buf);
468 have_error = TRUE(!(0));
469 }
470 if (tmp_buf->str[0] != 0)
471 module->info->domain = g_strdup (tmp_buf->str)g_strdup_inline (tmp_buf->str);
472
473 if (!scan_string (&p, tmp_buf)) {
474 g_warning ("Error parsing loader info in '%s'\n %s",
475 filename, line_buf);
476 have_error = TRUE(!(0));
477 }
478 module->info->description = g_strdup (tmp_buf->str)g_strdup_inline (tmp_buf->str);
479
480 if (scan_string (&p, tmp_buf)) {
481 module->info->license = g_strdup (tmp_buf->str)g_strdup_inline (tmp_buf->str);
482 }
483 }
484 else if (!module->info->mime_types) {
485 int n = 1;
486 module->info->mime_types = g_new0 (gchar*, 1)(gchar* *) (__extension__ ({ gsize __n = (gsize) (1); gsize __s
= sizeof (gchar*); gpointer __p; if (__s == 1) __p = g_malloc0
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s); __p
; }))
;
487 while (scan_string (&p, tmp_buf)) {
488 if (tmp_buf->str[0] != 0) {
489 module->info->mime_types =
490 g_realloc (module->info->mime_types, (n + 1) * sizeof (gchar*));
491 module->info->mime_types[n - 1] = g_strdup (tmp_buf->str)g_strdup_inline (tmp_buf->str);
492 module->info->mime_types[n] = NULL((void*)0);
493 n++;
494 }
495 }
496 }
497 else if (!module->info->extensions) {
498 int n = 1;
499 module->info->extensions = g_new0 (gchar*, 1)(gchar* *) (__extension__ ({ gsize __n = (gsize) (1); gsize __s
= sizeof (gchar*); gpointer __p; if (__s == 1) __p = g_malloc0
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s); __p
; }))
;
500 while (scan_string (&p, tmp_buf)) {
501 if (tmp_buf->str[0] != 0) {
502 module->info->extensions =
503 g_realloc (module->info->extensions, (n + 1) * sizeof (gchar*));
504 module->info->extensions[n - 1] = g_strdup (tmp_buf->str)g_strdup_inline (tmp_buf->str);
505 module->info->extensions[n] = NULL((void*)0);
506 n++;
507 }
508 }
509 }
510 else {
511 n_patterns++;
512 module->info->signature = (CdkPixbufModulePattern *)
513 g_realloc (module->info->signature, (n_patterns + 1) * sizeof (CdkPixbufModulePattern));
514 pattern = module->info->signature + n_patterns;
515 pattern->prefix = NULL((void*)0);
516 pattern->mask = NULL((void*)0);
517 pattern->relevance = 0;
518 pattern--;
519 if (!scan_string (&p, tmp_buf))
520 goto context_error;
521 pattern->prefix = g_strdup (tmp_buf->str)g_strdup_inline (tmp_buf->str);
522
523 if (!scan_string (&p, tmp_buf))
524 goto context_error;
525 if (*tmp_buf->str)
526 pattern->mask = g_strdup (tmp_buf->str)g_strdup_inline (tmp_buf->str);
527 else
528 pattern->mask = NULL((void*)0);
529
530 if (!scan_int (&p, &pattern->relevance))
531 goto context_error;
532
533 goto next_line;
534
535 context_error:
536 g_free (pattern->prefix);
537 g_free (pattern->mask);
538 g_free (pattern);
539 g_warning ("Error parsing loader info in '%s'\n %s",
540 filename, line_buf);
541 have_error = TRUE(!(0));
542 }
543 next_line:
544 g_free (line_buf);
545 }
546 g_string_free (tmp_buf, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(tmp_buf), ((!(0)))) : g_string_free_and_steal (tmp_buf)) : (
g_string_free) ((tmp_buf), ((!(0)))))
;
29
Potential leak of memory pointed to by 'module'
547 g_io_channel_unref (channel);
548
549 if (g_slist_length (file_formats) <= num_formats) {
550 char *filename_utf8 = g_filename_display_name (filename);
551 g_set_error (error,
552 G_IO_ERRORg_io_error_quark(),
553 G_IO_ERROR_NOT_INITIALIZED,
554 "No new CdkPixbufModule loaded from '%s'",
555 filename_utf8);
556 g_free (filename_utf8);
557 return FALSE(0);
558 }
559#endif
560 return TRUE(!(0));
561}
562
563/**
564 * cdk_pixbuf_init_modules:
565 * @path: Path to directory where the `loaders.cache` is installed
566 * @error: return location for a `GError`
567 *
568 * Initalizes the cdk-pixbuf loader modules referenced by the `loaders.cache`
569 * file present inside that directory.
570 *
571 * This is to be used by applications that want to ship certain loaders
572 * in a different location from the system ones.
573 *
574 * This is needed when the OS or runtime ships a minimal number of loaders
575 * so as to reduce the potential attack surface of carefully crafted image
576 * files, especially for uncommon file types. Applications that require
577 * broader image file types coverage, such as image viewers, would be
578 * expected to ship the cdk-pixbuf modules in a separate location, bundled
579 * with the application in a separate directory from the OS or runtime-
580 * provided modules.
581 *
582 * Since: 2.40
583 */
584gboolean
585cdk_pixbuf_init_modules (const char *path,
586 GError **error)
587{
588 char *filename;
589 gboolean ret;
590
591 g_return_val_if_fail (path != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_89
= 0; if (path != ((void*)0)) _g_boolean_var_89 = 1; _g_boolean_var_89
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "path != NULL"); return ((0)); } }
while (0)
;
592 filename = g_build_filename (path, "loaders.cache", NULL((void*)0));
593 ret = cdk_pixbuf_io_init_modules (filename, error);
594 g_free (filename);
595 return ret;
596}
597
598static void
599cdk_pixbuf_io_init_builtin (void)
600{
601#define load_one_builtin_module(format) G_STMT_STARTdo { \
602 CdkPixbufModule *__builtin_module = g_new0 (CdkPixbufModule, 1)(CdkPixbufModule *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (CdkPixbufModule); gpointer __p; if (__s
== 1) __p = g_malloc0 (__n); else if (__builtin_constant_p (
__n) && (__s == 0 || __n <= (9223372036854775807L *
2UL+1UL) / __s)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n
(__n, __s); __p; }))
; \
603 __builtin_module->module_name = #format; \
604 if (cdk_pixbuf_load_module_unlocked (__builtin_module, NULL((void*)0))) \
605 file_formats = g_slist_prepend (file_formats, __builtin_module); \
606 else \
607 g_free (__builtin_module); } G_STMT_ENDwhile (0)
608
609#ifdef INCLUDE_ani
610 load_one_builtin_module (ani);
611#endif
612#ifdef INCLUDE_png
613 load_one_builtin_module (png);
614#endif
615#ifdef INCLUDE_bmp
616 load_one_builtin_module (bmp);
617#endif
618#ifdef INCLUDE_gif
619 load_one_builtin_module (gif);
620#endif
621#ifdef INCLUDE_ico
622 load_one_builtin_module (ico);
623#endif
624#ifdef INCLUDE_jpeg
625 load_one_builtin_module (jpeg);
626#endif
627#ifdef INCLUDE_pnm
628 load_one_builtin_module (pnm);
629#endif
630#ifdef INCLUDE_tiff
631 load_one_builtin_module (tiff);
632#endif
633#ifdef INCLUDE_xpm
634 load_one_builtin_module (xpm);
635#endif
636#ifdef INCLUDE_xbm
637 load_one_builtin_module (xbm);
638#endif
639#ifdef INCLUDE_tga
640 load_one_builtin_module (tga);
641#endif
642#ifdef INCLUDE_icns
643 load_one_builtin_module (icns);
644#endif
645#ifdef INCLUDE_qtif
646 load_one_builtin_module (qtif);
647#endif
648#ifdef INCLUDE_gdiplus
649 /* We don't bother having the GDI+ loaders individually selectable
650 * for building in or not.
651 */
652 load_one_builtin_module (ico);
653 load_one_builtin_module (wmf);
654 load_one_builtin_module (emf);
655 load_one_builtin_module (bmp);
656 load_one_builtin_module (gif);
657 load_one_builtin_module (jpeg);
658 load_one_builtin_module (tiff);
659#endif
660#ifdef INCLUDE_gdip_png
661 /* Except the gdip-png loader which normally isn't built at all even */
662 load_one_builtin_module (png);
663#endif
664#ifdef INCLUDE_glycin
665 load_one_builtin_module (avif);
666 load_one_builtin_module (bmp);
667 load_one_builtin_module (dds);
668 load_one_builtin_module (gif);
669 load_one_builtin_module (heic);
670 load_one_builtin_module (ico);
671 load_one_builtin_module (jpeg);
672 load_one_builtin_module (jxl);
673 load_one_builtin_module (openexr);
674 load_one_builtin_module (png);
675 load_one_builtin_module (pnm);
676 load_one_builtin_module (qoi);
677 load_one_builtin_module (raw);
678 load_one_builtin_module (svg);
679 load_one_builtin_module (tga);
680 load_one_builtin_module (tiff);
681 load_one_builtin_module (webp);
682 load_one_builtin_module (xbm);
683 load_one_builtin_module (xpm);
684#endif
685#ifdef INCLUDE_android
686 load_one_builtin_module (jpeg);
687 load_one_builtin_module (png);
688 load_one_builtin_module (gif);
689 load_one_builtin_module (webp);
690 load_one_builtin_module (bmp);
691 load_one_builtin_module (ico);
692 load_one_builtin_module (wbmp);
693 load_one_builtin_module (heif);
694#endif
695
696#undef load_one_builtin_module
697}
698
699static gboolean
700cdk_pixbuf_io_init (void)
701{
702#ifdef USE_GMODULE
703 char *module_file;
704
705 module_file = cdk_pixbuf_get_module_file ();
706 cdk_pixbuf_io_init_modules (module_file, NULL((void*)0));
13
Calling 'cdk_pixbuf_io_init_modules'
707 g_free (module_file);
708#endif
709
710 cdk_pixbuf_io_init_builtin ();
711
712 return file_formats != NULL((void*)0);
713}
714
715#define module(type) \
716 extern void _cdk_pixbuf__##type##_fill_info (CdkPixbufFormat *info); \
717 extern void _cdk_pixbuf__##type##_fill_vtable (CdkPixbufModule *module)
718
719module (png);
720module (jpeg);
721module (gif);
722module (ico);
723module (ani);
724module (xpm);
725module (tiff);
726module (pnm);
727module (bmp);
728module (xbm);
729module (tga);
730module (icns);
731module (qtif);
732module (gdip_ico);
733module (gdip_wmf);
734module (gdip_emf);
735module (gdip_bmp);
736module (gdip_gif);
737module (gdip_jpeg);
738module (gdip_png);
739module (gdip_tiff);
740
741module (glycin_avif);
742module (glycin_bmp);
743module (glycin_dds);
744module (glycin_gif);
745module (glycin_heic);
746module (glycin_ico);
747module (glycin_jpeg);
748module (glycin_jxl);
749module (glycin_openexr);
750module (glycin_png);
751module (glycin_pnm);
752module (glycin_qoi);
753module (glycin_raw);
754module (glycin_svg);
755module (glycin_tga);
756module (glycin_tiff);
757module (glycin_webp);
758module (glycin_xbm);
759module (glycin_xpm);
760
761module (android_jpeg);
762module (android_png);
763module (android_gif);
764module (android_webp);
765module (android_bmp);
766module (android_ico);
767module (android_wbmp);
768module (android_heif);
769
770#undef module
771
772/* actually load the image handler - cdk_pixbuf_get_module only get a */
773/* reference to the module to load, it doesn't actually load it */
774/* perhaps these actions should be combined in one function */
775static gboolean
776cdk_pixbuf_load_module_unlocked (CdkPixbufModule *image_module,
777 GError **error)
778{
779 CdkPixbufModuleFillInfoFunc fill_info = NULL((void*)0);
780 CdkPixbufModuleFillVtableFunc fill_vtable = NULL((void*)0);
781
782 if (image_module->module != NULL((void*)0))
783 return TRUE(!(0));
784
785#define try_module(format,id) \
786 if (fill_info == NULL((void*)0) && \
787 strcmp (image_module->module_name, #format) == 0) { \
788 fill_info = _cdk_pixbuf__##id##_fill_info; \
789 fill_vtable = _cdk_pixbuf__##id##_fill_vtable; \
790 }
791
792#ifdef INCLUDE_gdiplus
793 try_module (ico,gdip_ico);
794 try_module (wmf,gdip_wmf);
795 try_module (emf,gdip_emf);
796 try_module (bmp,gdip_bmp);
797 try_module (gif,gdip_gif);
798 try_module (jpeg,gdip_jpeg);
799 try_module (tiff,gdip_tiff);
800#endif
801#ifdef INCLUDE_gdip_png
802 try_module (png,gdip_png);
803#endif
804#ifdef INCLUDE_glycin
805 try_module (avif, glycin_avif);
806 try_module (bmp, glycin_bmp);
807 try_module (dds, glycin_dds);
808 try_module (gif, glycin_gif);
809 try_module (heic, glycin_heic);
810 try_module (ico, glycin_ico);
811 try_module (jpeg, glycin_jpeg);
812 try_module (jxl, glycin_jxl);
813 try_module (openexr, glycin_openexr);
814 try_module (png, glycin_png);
815 try_module (pnm, glycin_pnm);
816 try_module (qoi, glycin_qoi);
817 try_module (raw, glycin_raw);
818 try_module (svg, glycin_svg);
819 try_module (tga, glycin_tga);
820 try_module (tiff, glycin_tiff);
821 try_module (webp, glycin_webp);
822 try_module (xbm, glycin_xbm);
823 try_module (xpm, glycin_xpm);
824#endif
825#ifdef INCLUDE_android
826 try_module (jpeg,android_jpeg);
827 try_module (png,android_png);
828 try_module (gif,android_gif);
829 try_module (webp,android_webp);
830 try_module (bmp,android_bmp);
831 try_module (ico,android_ico);
832 try_module (wbmp,android_wbmp);
833 try_module (heif,android_heif);
834#endif
835#ifdef INCLUDE_png
836 try_module (png,png);
837#endif
838#ifdef INCLUDE_bmp
839 try_module (bmp,bmp);
840#endif
841#ifdef INCLUDE_gif
842 try_module (gif,gif);
843#endif
844#ifdef INCLUDE_ico
845 try_module (ico,ico);
846#endif
847#ifdef INCLUDE_ani
848 try_module (ani,ani);
849#endif
850#ifdef INCLUDE_jpeg
851 try_module (jpeg,jpeg);
852#endif
853#ifdef INCLUDE_pnm
854 try_module (pnm,pnm);
855#endif
856#ifdef INCLUDE_tiff
857 try_module (tiff,tiff);
858#endif
859#ifdef INCLUDE_xpm
860 try_module (xpm,xpm);
861#endif
862#ifdef INCLUDE_xbm
863 try_module (xbm,xbm);
864#endif
865#ifdef INCLUDE_tga
866 try_module (tga,tga);
867#endif
868#ifdef INCLUDE_icns
869 try_module (icns,icns);
870#endif
871#ifdef INCLUDE_qtif
872 try_module (qtif,qtif);
873#endif
874
875#undef try_module
876
877 if (fill_vtable) {
878 image_module->module = (void *) 1;
879 (* fill_vtable) (image_module);
880 if (image_module->info == NULL((void*)0)) {
881 image_module->info = g_new0 (CdkPixbufFormat, 1)(CdkPixbufFormat *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (CdkPixbufFormat); gpointer __p; if (__s
== 1) __p = g_malloc0 (__n); else if (__builtin_constant_p (
__n) && (__s == 0 || __n <= (9223372036854775807L *
2UL+1UL) / __s)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n
(__n, __s); __p; }))
;
882 (* fill_info) (image_module->info);
883 }
884 return TRUE(!(0));
885 }
886 else
887#ifdef USE_GMODULE
888 {
889 char *path;
890 GModule *module;
891 gpointer sym;
892
893 path = image_module->module_path;
894 module = g_module_open (path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
895
896 if (!module) {
897 char *path_utf8 = g_filename_display_name (path);
898 g_set_error (error,
899 CDK_PIXBUF_ERRORcdk_pixbuf_error_quark (),
900 CDK_PIXBUF_ERROR_FAILED,
901 _("Unable to load image-loading module: %s: %s")((char *) g_dgettext ("cdk-pixbuf", "Unable to load image-loading module: %s: %s"
))
,
902 path_utf8, g_module_error ());
903 g_free (path_utf8);
904 return FALSE(0);
905 }
906
907 image_module->module = module;
908
909
910 if (g_module_symbol (module, "fill_vtable", &sym)) {
911 fill_vtable = (CdkPixbufModuleFillVtableFunc) sym;
912 (* fill_vtable) (image_module);
913 return TRUE(!(0));
914 } else {
915 char *path_utf8 = g_filename_display_name (path);
916 g_set_error (error,
917 CDK_PIXBUF_ERRORcdk_pixbuf_error_quark (),
918 CDK_PIXBUF_ERROR_FAILED,
919 _("Image-loading module %s does not export the proper interface; perhaps it’s from a different cdk-pixbuf version?")((char *) g_dgettext ("cdk-pixbuf", "Image-loading module %s does not export the proper interface; perhaps it’s from a different cdk-pixbuf version?"
))
,
920 path_utf8);
921 g_free (path_utf8);
922 return FALSE(0);
923 }
924 }
925#else
926 g_set_error (error,
927 CDK_PIXBUF_ERRORcdk_pixbuf_error_quark (),
928 CDK_PIXBUF_ERROR_UNKNOWN_TYPE,
929 _("Image type “%s” is not supported")((char *) g_dgettext ("cdk-pixbuf", "Image type “%s” is not supported"
))
,
930 image_module->module_name);
931 return FALSE(0);
932#endif /* !USE_GMODULE */
933}
934
935
936gboolean
937_cdk_pixbuf_load_module (CdkPixbufModule *image_module,
938 GError **error)
939{
940 gboolean ret;
941
942 G_LOCK (init_lock)g_mutex_lock (&g__init_lock_lock);
943
944 ret = cdk_pixbuf_load_module_unlocked (image_module, error);
945
946 G_UNLOCK (init_lock)g_mutex_unlock (&g__init_lock_lock);
947
948 return ret;
949}
950
951
952
953CdkPixbufModule *
954_cdk_pixbuf_get_named_module (const char *name,
955 GError **error)
956{
957 GSList *modules;
958
959 for (modules = get_file_formats (); modules; modules = g_slist_next (modules)((modules) ? (((GSList *)(modules))->next) : ((void*)0))) {
10
Calling 'get_file_formats'
960 CdkPixbufModule *module = (CdkPixbufModule *)modules->data;
961
962 if (module->info->disabled)
963 continue;
964
965 if (!strcmp (name, module->module_name))
966 return module;
967 }
968
969 g_set_error (error,
970 CDK_PIXBUF_ERRORcdk_pixbuf_error_quark (),
971 CDK_PIXBUF_ERROR_UNKNOWN_TYPE,
972 _("Image type “%s” is not supported")((char *) g_dgettext ("cdk-pixbuf", "Image type “%s” is not supported"
))
,
973 name);
974
975 return NULL((void*)0);
976}
977
978CdkPixbufModule *
979_cdk_pixbuf_get_module (guchar *buffer, guint size,
980 const gchar *filename,
981 GError **error)
982{
983 GSList *modules;
984
985 CdkPixbufModule *selected = NULL((void*)0);
986 gchar *display_name = NULL((void*)0);
987#ifdef CDK_PIXBUF_USE_GIO_MIME1
988 gchar *mime_type;
989 gchar **mimes;
990 gchar *type;
991 gint j;
992 gboolean uncertain;
993
994 mime_type = g_content_type_guess (NULL((void*)0), buffer, size, &uncertain);
995 if ((uncertain || g_str_equal (mime_type, "text/plain")(strcmp ((const char *) (mime_type), (const char *) ("text/plain"
)) == 0)
|| g_str_equal (mime_type, "application/gzip")(strcmp ((const char *) (mime_type), (const char *) ("application/gzip"
)) == 0)
) && filename != NULL((void*)0)) {
996 g_free (mime_type);
997 mime_type = g_content_type_guess (filename, buffer, size, NULL((void*)0));
998 }
999
1000 for (modules = get_file_formats (); modules; modules = g_slist_next (modules)((modules) ? (((GSList *)(modules))->next) : ((void*)0))) {
1001 CdkPixbufModule *module = (CdkPixbufModule *)modules->data;
1002 CdkPixbufFormat *info = module->info;
1003
1004 if (info->disabled)
1005 continue;
1006
1007 mimes = info->mime_types;
1008 for (j = 0; mimes[j] != NULL((void*)0); j++) {
1009 type = g_content_type_from_mime_type (mimes[j]);
1010 if (g_content_type_equals (type, mime_type)) {
1011 g_free (type);
1012 selected = module;
1013 break;
1014 }
1015 g_free (type);
1016 }
1017
1018 if (selected != NULL((void*)0))
1019 break;
1020
1021 /* Make sure the builtin CdkPixdata support works even without mime sniffing */
1022 if (strcmp (info->name, "CdkPixdata") == 0 &&
1023 format_check (module, buffer, size) == 100) {
1024 selected = module;
1025 break;
1026 }
1027 }
1028 g_free (mime_type);
1029#else
1030 gint score, best = 0;
1031
1032 for (modules = get_file_formats (); modules; modules = g_slist_next (modules)((modules) ? (((GSList *)(modules))->next) : ((void*)0))) {
1033 CdkPixbufModule *module = (CdkPixbufModule *)modules->data;
1034
1035 if (module->info->disabled)
1036 continue;
1037
1038 score = format_check (module, buffer, size);
1039 if (score > best) {
1040 best = score;
1041 selected = module;
1042 }
1043 if (score >= 100)
1044 break;
1045 }
1046#endif
1047
1048 if (selected != NULL((void*)0))
1049 return selected;
1050
1051 if (filename)
1052 {
1053 display_name = g_filename_display_name (filename);
1054 g_set_error (error,
1055 CDK_PIXBUF_ERRORcdk_pixbuf_error_quark (),
1056 CDK_PIXBUF_ERROR_UNKNOWN_TYPE,
1057 _("Couldn’t recognize the image file format for file “%s”")((char *) g_dgettext ("cdk-pixbuf", "Couldn’t recognize the image file format for file “%s”"
))
,
1058 display_name);
1059 g_free (display_name);
1060 }
1061 else
1062 g_set_error_literal (error,
1063 CDK_PIXBUF_ERRORcdk_pixbuf_error_quark (),
1064 CDK_PIXBUF_ERROR_UNKNOWN_TYPE,
1065 _("Unrecognized image file format")((char *) g_dgettext ("cdk-pixbuf", "Unrecognized image file format"
))
);
1066
1067
1068 return NULL((void*)0);
1069}
1070
1071static
1072CdkPixbufModule *
1073_cdk_pixbuf_get_module_for_file (FILE *f, const gchar *filename, GError **error)
1074{
1075 guchar buffer[SNIFF_BUFFER_SIZE4096];
1076 int size;
1077
1078 size = fread (&buffer, 1, sizeof (buffer), f);
1079 if (size == 0) {
1080 gchar *display_name;
1081 display_name = g_filename_display_name (filename);
1082 g_set_error (error,
1083 CDK_PIXBUF_ERRORcdk_pixbuf_error_quark (),
1084 CDK_PIXBUF_ERROR_CORRUPT_IMAGE,
1085 _("Image file “%s” contains no data")((char *) g_dgettext ("cdk-pixbuf", "Image file “%s” contains no data"
))
,
1086 display_name);
1087 g_free (display_name);
1088 return NULL((void*)0);
1089 }
1090
1091 return _cdk_pixbuf_get_module (buffer, size, filename, error);
1092}
1093
1094static void
1095noop_size_notify (gint *width,
1096 gint *height,
1097 gpointer data)
1098{
1099}
1100
1101static void
1102prepared_notify (CdkPixbuf *pixbuf,
1103 CdkPixbufAnimation *anim,
1104 gpointer user_data)
1105{
1106 if (pixbuf != NULL((void*)0))
1107 g_object_ref (pixbuf)((__typeof__ (pixbuf)) (g_object_ref) (pixbuf));
1108 *((CdkPixbuf **)user_data) = pixbuf;
1109}
1110
1111static void
1112noop_updated_notify (CdkPixbuf *pixbuf,
1113 int x,
1114 int y,
1115 int width,
1116 int height,
1117 gpointer user_data)
1118{
1119}
1120
1121static CdkPixbuf *
1122generic_load_incrementally (CdkPixbufModule *module, FILE *f, GError **error)
1123{
1124 CdkPixbuf *pixbuf = NULL((void*)0);
1125 gpointer context;
1126
1127 context = module->begin_load (noop_size_notify, prepared_notify, noop_updated_notify, &pixbuf, error);
1128
1129 if (!context)
1130 goto out;
1131
1132 while (!feof (f) && !ferror (f)) {
1133 guchar buffer[LOAD_BUFFER_SIZE65536];
1134 size_t length;
1135
1136 length = fread (buffer, 1, sizeof (buffer), f);
1137 if (length > 0) {
1138 if (!module->load_increment (context, buffer, length, error)) {
1139 module->stop_load (context, NULL((void*)0));
1140 if (pixbuf != NULL((void*)0)) {
1141 g_object_unref (pixbuf);
1142 pixbuf = NULL((void*)0);
1143 }
1144 goto out;
1145 }
1146 }
1147 }
1148
1149 if (!module->stop_load (context, error)) {
1150 if (pixbuf != NULL((void*)0)) {
1151 g_object_unref (pixbuf);
1152 pixbuf = NULL((void*)0);
1153 }
1154 }
1155
1156out:
1157 return pixbuf;
1158}
1159
1160CdkPixbuf *
1161_cdk_pixbuf_generic_image_load (CdkPixbufModule *module, FILE *f, GError **error)
1162{
1163 CdkPixbuf *pixbuf = NULL((void*)0);
1164
1165 if (module->load != NULL((void*)0)) {
1166 pixbuf = (* module->load) (f, error);
1167 } else if (module->begin_load != NULL((void*)0)) {
1168 pixbuf = generic_load_incrementally (module, f, error);
1169 } else if (module->load_animation != NULL((void*)0)) {
1170 CdkPixbufAnimation *animation;
1171
1172 animation = (* module->load_animation) (f, error);
1173 if (animation != NULL((void*)0)) {
1174 pixbuf = cdk_pixbuf_animation_get_static_image (animation);
1175
1176 g_object_ref (pixbuf)((__typeof__ (pixbuf)) (g_object_ref) (pixbuf));
1177 g_object_unref (animation);
1178 }
1179 }
1180
1181 return pixbuf;
1182}
1183
1184/**
1185 * cdk_pixbuf_new_from_file: (constructor)
1186 * @filename: (type filename): Name of file to load, in the GLib file
1187 * name encoding
1188 * @error: (out): Return location for an error
1189 *
1190 * Creates a new pixbuf by loading an image from a file.
1191 *
1192 * The file format is detected automatically.
1193 *
1194 * If `NULL` is returned, then @error will be set. Possible errors are:
1195 *
1196 * - the file could not be opened
1197 * - there is no loader for the file's format
1198 * - there is not enough memory to allocate the image buffer
1199 * - the image buffer contains invalid data
1200 *
1201 * The error domains are `CDK_PIXBUF_ERROR` and `G_FILE_ERROR`.
1202 *
1203 * Returns: (nullable): A newly-created pixbuf
1204 */
1205CdkPixbuf *
1206cdk_pixbuf_new_from_file (const char *filename,
1207 GError **error)
1208{
1209 CdkPixbuf *pixbuf;
1210 FILE *f;
1211 CdkPixbufModule *image_module;
1212
1213 g_return_val_if_fail (filename != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_90
= 0; if (filename != ((void*)0)) _g_boolean_var_90 = 1; _g_boolean_var_90
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "filename != NULL"); return (((void
*)0)); } } while (0)
;
1214 g_return_val_if_fail (error == NULL || *error == NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_91
= 0; if (error == ((void*)0) || *error == ((void*)0)) _g_boolean_var_91
= 1; _g_boolean_var_91; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "error == NULL || *error == NULL"
); return (((void*)0)); } } while (0)
;
1215
1216 f = g_fopenfopen (filename, "rb");
1217 if (!f) {
1218 gint save_errno = errno(*__errno_location ());
1219 gchar *display_name;
1220 display_name = g_filename_display_name (filename);
1221 g_set_error (error,
1222 G_FILE_ERRORg_file_error_quark (),
1223 g_file_error_from_errno (save_errno),
1224 _("Failed to open file “%s”: %s")((char *) g_dgettext ("cdk-pixbuf", "Failed to open file “%s”: %s"
))
,
1225 display_name,
1226 g_strerror (save_errno));
1227 g_free (display_name);
1228 return NULL((void*)0);
1229 }
1230
1231 image_module = _cdk_pixbuf_get_module_for_file (f, filename, error);
1232 if (image_module == NULL((void*)0)) {
1233 fclose (f);
1234 return NULL((void*)0);
1235 }
1236
1237 if (!_cdk_pixbuf_load_module (image_module, error)) {
1238 fclose (f);
1239 return NULL((void*)0);
1240 }
1241
1242 fseek (f, 0, SEEK_SET0);
1243 pixbuf = _cdk_pixbuf_generic_image_load (image_module, f, error);
1244 fclose (f);
1245
1246 if (pixbuf == NULL((void*)0) && error != NULL((void*)0) && *error == NULL((void*)0)) {
1247
1248 /* I don't trust these crufty longjmp()'ing image libs
1249 * to maintain proper error invariants, and I don't
1250 * want user code to segfault as a result. We need to maintain
1251 * the invariant that error gets set if NULL is returned.
1252 */
1253
1254 gchar *display_name;
1255 display_name = g_filename_display_name (filename);
1256 g_warning ("Bug! cdk-pixbuf loader '%s' didn't set an error on failure.", image_module->module_name);
1257 g_set_error (error,
1258 CDK_PIXBUF_ERRORcdk_pixbuf_error_quark (),
1259 CDK_PIXBUF_ERROR_FAILED,
1260 _("Failed to load image “%s”: reason not known, probably a corrupt image file")((char *) g_dgettext ("cdk-pixbuf", "Failed to load image “%s”: reason not known, probably a corrupt image file"
))
,
1261 display_name);
1262 g_free (display_name);
1263 } else if (error != NULL((void*)0) && *error != NULL((void*)0)) {
1264 /* Add the filename to the error message */
1265 GError *e = *error;
1266 gchar *old;
1267 gchar *display_name;
1268
1269 display_name = g_filename_display_name (filename);
1270 old = e->message;
1271 e->message = g_strdup_printf (_("Failed to load image “%s”: %s")((char *) g_dgettext ("cdk-pixbuf", "Failed to load image “%s”: %s"
))
,
1272 display_name,
1273 old);
1274 g_free (old);
1275 g_free (display_name);
1276 }
1277
1278 return pixbuf;
1279}
1280
1281#ifdef G_OS_WIN32
1282
1283/**
1284 * cdk_pixbuf_new_from_file_utf8: (constructor)
1285 * @filename: (type filename): Name of file to load, in the GLib file name encoding
1286 * @error: Return location for an error
1287 *
1288 * Same as cdk_pixbuf_new_from_file()
1289 *
1290 * Returns: (nullable): A newly-created pixbuf with a reference count of 1,
1291 * or `NULL` if any of several error conditions occurred: the file could not be opened,
1292 * there was no loader for the file's format, there was not enough memory to
1293 * allocate the image buffer, or the image file contained invalid data.
1294 **/
1295CdkPixbuf *
1296cdk_pixbuf_new_from_file_utf8 (const char *filename,
1297 GError **error)
1298{
1299 return cdk_pixbuf_new_from_file (filename, error);
1300}
1301
1302#endif
1303
1304
1305/**
1306 * cdk_pixbuf_new_from_file_at_size: (constructor)
1307 * @filename: (type filename): Name of file to load, in the GLib file
1308 * name encoding
1309 * @width: The width the image should have or -1 to not constrain the width
1310 * @height: The height the image should have or -1 to not constrain the height
1311 * @error: (out): Return location for an error
1312 *
1313 * Creates a new pixbuf by loading an image from a file.
1314 *
1315 * The file format is detected automatically.
1316 *
1317 * If `NULL` is returned, then @error will be set. Possible errors are:
1318 *
1319 * - the file could not be opened
1320 * - there is no loader for the file's format
1321 * - there is not enough memory to allocate the image buffer
1322 * - the image buffer contains invalid data
1323 *
1324 * The error domains are `CDK_PIXBUF_ERROR` and `G_FILE_ERROR`.
1325 *
1326 * The image will be scaled to fit in the requested size, preserving
1327 * the image's aspect ratio. Note that the returned pixbuf may be smaller
1328 * than `width` x `height`, if the aspect ratio requires it. To load
1329 * and image at the requested size, regardless of aspect ratio, use
1330 * [ctor@CdkPixbuf.Pixbuf.new_from_file_at_scale].
1331 *
1332 * Returns: (nullable): A newly-created pixbuf
1333 *
1334 * Since: 2.4
1335 **/
1336CdkPixbuf *
1337cdk_pixbuf_new_from_file_at_size (const char *filename,
1338 int width,
1339 int height,
1340 GError **error)
1341{
1342 return cdk_pixbuf_new_from_file_at_scale (filename,
1343 width, height,
1344 TRUE(!(0)), error);
1345}
1346
1347#ifdef G_OS_WIN32
1348
1349/**
1350 * cdk_pixbuf_new_from_file_at_size_utf8: (constructor)
1351 * @filename: (type filename): Name of file to load, in the GLib file name encoding
1352 * @width: The width the image should have or -1 to not constrain the width
1353 * @height: The height the image should have or -1 to not constrain the height
1354 * @error: Return location for an error
1355 *
1356 * Same as cdk_pixbuf_new_from_file_at_size()
1357 *
1358 * Returns: (nullable): A newly-created pixbuf with a reference count of 1, or
1359 * `NULL` if any of several error conditions occurred: the file could not
1360 * be opened, there was no loader for the file's format, there was not
1361 * enough memory to allocate the image buffer, or the image file contained
1362 * invalid data.
1363 *
1364 * Since: 2.4
1365 **/
1366CdkPixbuf *
1367cdk_pixbuf_new_from_file_at_size_utf8 (const char *filename,
1368 int width,
1369 int height,
1370 GError **error)
1371{
1372 return cdk_pixbuf_new_from_file_at_size (filename, width, height, error);
1373}
1374
1375#endif
1376
1377typedef struct {
1378 gint width;
1379 gint height;
1380 gboolean preserve_aspect_ratio;
1381} AtScaleData;
1382
1383static void
1384at_scale_data_async_data_free (AtScaleData *data)
1385{
1386 g_slice_free (AtScaleData, data)do { if (1) g_slice_free1 (sizeof (AtScaleData), (data)); else
(void) ((AtScaleData*) 0 == (data)); } while (0)
;
1387}
1388
1389static void
1390at_scale_size_prepared_cb (CdkPixbufLoader *loader,
1391 int width,
1392 int height,
1393 gpointer data)
1394{
1395 AtScaleData *info = data;
1396
1397 g_return_if_fail (width > 0 && height > 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_92
= 0; if (width > 0 && height > 0) _g_boolean_var_92
= 1; _g_boolean_var_92; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "width > 0 && height > 0"
); return; } } while (0)
;
1398
1399 if (info->preserve_aspect_ratio &&
1400 (info->width > 0 || info->height > 0)) {
1401 if (info->width < 0)
1402 {
1403 width = width * (double)info->height/(double)height;
1404 height = info->height;
1405 }
1406 else if (info->height < 0)
1407 {
1408 height = height * (double)info->width/(double)width;
1409 width = info->width;
1410 }
1411 else if ((double)height * (double)info->width >
1412 (double)width * (double)info->height) {
1413 width = 0.5 + (double)width * (double)info->height / (double)height;
1414 height = info->height;
1415 } else {
1416 height = 0.5 + (double)height * (double)info->width / (double)width;
1417 width = info->width;
1418 }
1419 } else {
1420 if (info->width > 0)
1421 width = info->width;
1422 if (info->height > 0)
1423 height = info->height;
1424 }
1425
1426 width = MAX (width, 1)(((width) > (1)) ? (width) : (1));
1427 height = MAX (height, 1)(((height) > (1)) ? (height) : (1));
1428
1429 cdk_pixbuf_loader_set_size (loader, width, height);
1430}
1431
1432/**
1433 * cdk_pixbuf_new_from_file_at_scale: (constructor)
1434 * @filename: (type filename): Name of file to load, in the GLib file
1435 * name encoding
1436 * @width: The width the image should have or -1 to not constrain the width
1437 * @height: The height the image should have or -1 to not constrain the height
1438 * @preserve_aspect_ratio: `TRUE` to preserve the image's aspect ratio
1439 * @error: Return location for an error
1440 *
1441 * Creates a new pixbuf by loading an image from a file.
1442 *
1443 * The file format is detected automatically.
1444 *
1445 * If `NULL` is returned, then @error will be set. Possible errors are:
1446 *
1447 * - the file could not be opened
1448 * - there is no loader for the file's format
1449 * - there is not enough memory to allocate the image buffer
1450 * - the image buffer contains invalid data
1451 *
1452 * The error domains are `CDK_PIXBUF_ERROR` and `G_FILE_ERROR`.
1453 *
1454 * The image will be scaled to fit in the requested size, optionally preserving
1455 * the image's aspect ratio.
1456 *
1457 * When preserving the aspect ratio, a `width` of -1 will cause the image
1458 * to be scaled to the exact given height, and a `height` of -1 will cause
1459 * the image to be scaled to the exact given width. When not preserving
1460 * aspect ratio, a `width` or `height` of -1 means to not scale the image
1461 * at all in that dimension. Negative values for `width` and `height` are
1462 * allowed since 2.8.
1463 *
1464 * Returns: (nullable): A newly-created pixbuf
1465 *
1466 * Since: 2.6
1467 **/
1468CdkPixbuf *
1469cdk_pixbuf_new_from_file_at_scale (const char *filename,
1470 int width,
1471 int height,
1472 gboolean preserve_aspect_ratio,
1473 GError **error)
1474{
1475
1476 CdkPixbufLoader *loader;
1477 CdkPixbuf *pixbuf;
1478 guchar buffer[LOAD_BUFFER_SIZE65536];
1479 int length;
1480 FILE *f;
1481 AtScaleData info;
1482 CdkPixbufAnimation *animation;
1483 CdkPixbufAnimationIter *iter;
1484 gboolean has_frame;
1485
1486 g_return_val_if_fail (filename != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_93
= 0; if (filename != ((void*)0)) _g_boolean_var_93 = 1; _g_boolean_var_93
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "filename != NULL"); return (((void
*)0)); } } while (0)
;
1487 g_return_val_if_fail (width > 0 || width == -1, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_94
= 0; if (width > 0 || width == -1) _g_boolean_var_94 = 1;
_g_boolean_var_94; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "width > 0 || width == -1"
); return (((void*)0)); } } while (0)
;
1488 g_return_val_if_fail (height > 0 || height == -1, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_95
= 0; if (height > 0 || height == -1) _g_boolean_var_95 = 1
; _g_boolean_var_95; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "height > 0 || height == -1"
); return (((void*)0)); } } while (0)
;
1489
1490 f = g_fopenfopen (filename, "rb");
1491 if (!f) {
1492 gint save_errno = errno(*__errno_location ());
1493 gchar *display_name = g_filename_display_name (filename);
1494 g_set_error (error,
1495 G_FILE_ERRORg_file_error_quark (),
1496 g_file_error_from_errno (save_errno),
1497 _("Failed to open file “%s”: %s")((char *) g_dgettext ("cdk-pixbuf", "Failed to open file “%s”: %s"
))
,
1498 display_name,
1499 g_strerror (save_errno));
1500 g_free (display_name);
1501 return NULL((void*)0);
1502 }
1503
1504 loader = _cdk_pixbuf_loader_new_with_filename (filename);
1505
1506 info.width = width;
1507 info.height = height;
1508 info.preserve_aspect_ratio = preserve_aspect_ratio;
1509
1510 g_signal_connect (loader, "size-prepared",g_signal_connect_data ((loader), ("size-prepared"), (((GCallback
) (at_scale_size_prepared_cb))), (&info), ((void*)0), (GConnectFlags
) 0)
1511 G_CALLBACK (at_scale_size_prepared_cb), &info)g_signal_connect_data ((loader), ("size-prepared"), (((GCallback
) (at_scale_size_prepared_cb))), (&info), ((void*)0), (GConnectFlags
) 0)
;
1512
1513 has_frame = FALSE(0);
1514 while (!has_frame && !feof (f) && !ferror (f)) {
1515 length = fread (buffer, 1, sizeof (buffer), f);
1516 if (length > 0)
1517 if (!cdk_pixbuf_loader_write (loader, buffer, length, error)) {
1518 cdk_pixbuf_loader_close (loader, NULL((void*)0));
1519 fclose (f);
1520 g_object_unref (loader);
1521 return NULL((void*)0);
1522 }
1523
1524 animation = cdk_pixbuf_loader_get_animation (loader);
1525 if (animation) {
1526 iter = cdk_pixbuf_animation_get_iter (animation, NULL((void*)0));
1527 if (!cdk_pixbuf_animation_iter_on_currently_loading_frame (iter)) {
1528 has_frame = TRUE(!(0));
1529 }
1530 g_object_unref (iter);
1531 }
1532 }
1533
1534 fclose (f);
1535
1536 if (!cdk_pixbuf_loader_close (loader, error) && !has_frame) {
1537 g_object_unref (loader);
1538 return NULL((void*)0);
1539 }
1540
1541 pixbuf = cdk_pixbuf_loader_get_pixbuf (loader);
1542
1543 if (!pixbuf) {
1544 gchar *display_name = g_filename_display_name (filename);
1545 g_object_unref (loader);
1546 g_set_error (error,
1547 CDK_PIXBUF_ERRORcdk_pixbuf_error_quark (),
1548 CDK_PIXBUF_ERROR_FAILED,
1549 _("Failed to load image “%s”: reason not known, probably a corrupt image file")((char *) g_dgettext ("cdk-pixbuf", "Failed to load image “%s”: reason not known, probably a corrupt image file"
))
,
1550 display_name);
1551 g_free (display_name);
1552 return NULL((void*)0);
1553 }
1554
1555 g_object_ref (pixbuf)((__typeof__ (pixbuf)) (g_object_ref) (pixbuf));
1556
1557 g_object_unref (loader);
1558
1559 return pixbuf;
1560}
1561
1562#ifdef G_OS_WIN32
1563
1564/**
1565 * cdk_pixbuf_new_from_file_at_scale_utf8: (constructor)
1566 * @filename: (type filename): Name of file to load, in the GLib file name encoding
1567 * @width: The width the image should have or -1 to not constrain the width
1568 * @height: The height the image should have or -1 to not constrain the height
1569 * @preserve_aspect_ratio: `TRUE` to preserve the image's aspect ratio
1570 * @error: Return location for an error
1571 *
1572 * Same as cdk_pixbuf_new_from_file_at_scale().
1573 *
1574 * Returns: (nullable): A newly-created pixbuf with a reference count of 1,
1575 * or `NULL` if any of several error conditions occurred: the file could not be opened,
1576 * there was no loader for the file's format, there was not enough memory to
1577 * allocate the image buffer, or the image file contained invalid data.
1578 *
1579 * Since: 2.6
1580 **/
1581CdkPixbuf *
1582cdk_pixbuf_new_from_file_at_scale_utf8 (const char *filename,
1583 int width,
1584 int height,
1585 gboolean preserve_aspect_ratio,
1586 GError **error)
1587{
1588 return cdk_pixbuf_new_from_file_at_scale (filename, width, height,
1589 preserve_aspect_ratio, error);
1590}
1591#endif
1592
1593
1594static CdkPixbuf *
1595load_from_stream (CdkPixbufLoader *loader,
1596 GInputStream *stream,
1597 GCancellable *cancellable,
1598 GError **error)
1599{
1600 CdkPixbuf *pixbuf;
1601 gssize n_read;
1602 guchar buffer[LOAD_BUFFER_SIZE65536];
1603
1604 while (1) {
1605 n_read = g_input_stream_read (stream,
1606 buffer,
1607 sizeof (buffer),
1608 cancellable,
1609 error);
1610 if (n_read < 0) {
1611 cdk_pixbuf_loader_close (loader, NULL((void*)0));
1612 return NULL((void*)0);
1613 }
1614
1615 if (n_read == 0)
1616 break;
1617
1618 if (!cdk_pixbuf_loader_write (loader,
1619 buffer,
1620 n_read,
1621 error)) {
1622 cdk_pixbuf_loader_close (loader, NULL((void*)0));
1623 return NULL((void*)0);
1624 }
1625 }
1626
1627 if (!cdk_pixbuf_loader_close (loader, error))
1628 return NULL((void*)0);
1629
1630 pixbuf = cdk_pixbuf_loader_get_pixbuf (loader);
1631 if (pixbuf == NULL((void*)0))
1632 return NULL((void*)0);
1633
1634 return g_object_ref (pixbuf)((__typeof__ (pixbuf)) (g_object_ref) (pixbuf));
1635}
1636
1637
1638/**
1639 * cdk_pixbuf_new_from_stream_at_scale: (constructor)
1640 * @stream: a `GInputStream` to load the pixbuf from
1641 * @width: The width the image should have or -1 to not constrain the width
1642 * @height: The height the image should have or -1 to not constrain the height
1643 * @preserve_aspect_ratio: `TRUE` to preserve the image's aspect ratio
1644 * @cancellable: (allow-none): optional `GCancellable` object, `NULL` to ignore
1645 * @error: Return location for an error
1646 *
1647 * Creates a new pixbuf by loading an image from an input stream.
1648 *
1649 * The file format is detected automatically. If `NULL` is returned, then
1650 * @error will be set. The @cancellable can be used to abort the operation
1651 * from another thread. If the operation was cancelled, the error
1652 * `G_IO_ERROR_CANCELLED` will be returned. Other possible errors are in
1653 * the `CDK_PIXBUF_ERROR` and `G_IO_ERROR` domains.
1654 *
1655 * The image will be scaled to fit in the requested size, optionally
1656 * preserving the image's aspect ratio.
1657 *
1658 * When preserving the aspect ratio, a `width` of -1 will cause the image to be
1659 * scaled to the exact given height, and a `height` of -1 will cause the image
1660 * to be scaled to the exact given width. If both `width` and `height` are
1661 * given, this function will behave as if the smaller of the two values
1662 * is passed as -1.
1663 *
1664 * When not preserving aspect ratio, a `width` or `height` of -1 means to not
1665 * scale the image at all in that dimension.
1666 *
1667 * The stream is not closed.
1668 *
1669 * Returns: (nullable): A newly-created pixbuf
1670 *
1671 * Since: 2.14
1672 */
1673CdkPixbuf *
1674cdk_pixbuf_new_from_stream_at_scale (GInputStream *stream,
1675 gint width,
1676 gint height,
1677 gboolean preserve_aspect_ratio,
1678 GCancellable *cancellable,
1679 GError **error)
1680{
1681 CdkPixbufLoader *loader;
1682 CdkPixbuf *pixbuf;
1683 AtScaleData info;
1684
1685 loader = cdk_pixbuf_loader_new ();
1686 info.width = width;
1687 info.height = height;
1688 info.preserve_aspect_ratio = preserve_aspect_ratio;
1689
1690 g_signal_connect (loader, "size-prepared",g_signal_connect_data ((loader), ("size-prepared"), (((GCallback
) (at_scale_size_prepared_cb))), (&info), ((void*)0), (GConnectFlags
) 0)
1691 G_CALLBACK (at_scale_size_prepared_cb), &info)g_signal_connect_data ((loader), ("size-prepared"), (((GCallback
) (at_scale_size_prepared_cb))), (&info), ((void*)0), (GConnectFlags
) 0)
;
1692
1693 pixbuf = load_from_stream (loader, stream, cancellable, error);
1694 g_object_unref (loader);
1695
1696 return pixbuf;
1697}
1698
1699
1700static void
1701load_from_stream_async_cb (GObject *stream,
1702 GAsyncResult *res,
1703 gpointer data)
1704{
1705 GTask *task = data;
1706 CdkPixbufLoader *loader;
1707 CdkPixbuf *pixbuf;
1708 GError *error = NULL((void*)0);
1709 GBytes *bytes = NULL((void*)0);
1710
1711 loader = g_task_get_task_data (task);
1712
1713 bytes = g_input_stream_read_bytes_finish (G_INPUT_STREAM (stream)((((GInputStream*) (void *) ((stream))))), res, &error);
1714
1715 if (bytes == NULL((void*)0)) {
1716 cdk_pixbuf_loader_close (loader, NULL((void*)0));
1717 g_task_return_error (task, error);
1718 } else if (g_bytes_get_size (bytes) > 0) {
1719 if (!cdk_pixbuf_loader_write (loader,
1720 g_bytes_get_data (bytes, NULL((void*)0)),
1721 g_bytes_get_size (bytes),
1722 &error)) {
1723 cdk_pixbuf_loader_close (loader, NULL((void*)0));
1724 g_task_return_error (task, error);
1725 goto out;
1726 }
1727 g_input_stream_read_bytes_async (G_INPUT_STREAM (stream)((((GInputStream*) (void *) ((stream))))),
1728 LOAD_BUFFER_SIZE65536,
1729 G_PRIORITY_DEFAULT0,
1730 g_task_get_cancellable (task),
1731 load_from_stream_async_cb,
1732 g_object_ref (task)((__typeof__ (task)) (g_object_ref) (task)));
1733
1734 } else {
1735 if (!cdk_pixbuf_loader_close (loader, &error)) {
1736 g_task_return_error (task, error);
1737 goto out;
1738 }
1739
1740 pixbuf = cdk_pixbuf_loader_get_pixbuf (loader);
1741 g_task_return_pointer (task, g_object_ref (pixbuf)((__typeof__ (pixbuf)) (g_object_ref) (pixbuf)), g_object_unref);
1742 }
1743
1744out:
1745 g_bytes_unref (bytes);
1746 g_object_unref (task);
1747}
1748
1749
1750/**
1751 * cdk_pixbuf_new_from_stream_at_scale_async: (finish-func cdk_pixbuf_new_from_stream_finish)
1752 * @stream: a `GInputStream` from which to load the pixbuf
1753 * @width: the width the image should have or -1 to not constrain the width
1754 * @height: the height the image should have or -1 to not constrain the height
1755 * @preserve_aspect_ratio: `TRUE` to preserve the image's aspect ratio
1756 * @cancellable: (nullable): optional `GCancellable` object, `NULL` to ignore
1757 * @callback: (scope async) (closure user_data): a `GAsyncReadyCallback` to call when the pixbuf is loaded
1758 * @user_data: the data to pass to the callback function
1759 *
1760 * Creates a new pixbuf by asynchronously loading an image from an input stream.
1761 *
1762 * For more details see cdk_pixbuf_new_from_stream_at_scale(), which is the synchronous
1763 * version of this function.
1764 *
1765 * When the operation is finished, @callback will be called in the main thread.
1766 * You can then call cdk_pixbuf_new_from_stream_finish() to get the result of the operation.
1767 *
1768 * Since: 2.24
1769 **/
1770void
1771cdk_pixbuf_new_from_stream_at_scale_async (GInputStream *stream,
1772 gint width,
1773 gint height,
1774 gboolean preserve_aspect_ratio,
1775 GCancellable *cancellable,
1776 GAsyncReadyCallback callback,
1777 gpointer user_data)
1778{
1779 GTask *task;
1780 AtScaleData *data;
1781 CdkPixbufLoader *loader;
1782
1783 g_return_if_fail (G_IS_INPUT_STREAM (stream))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_96
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stream)); GType __t = ((g_input_stream_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_96
= 1; _g_boolean_var_96; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "G_IS_INPUT_STREAM (stream)"
); return; } } while (0)
;
1784 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_97
= 0; if (callback != ((void*)0)) _g_boolean_var_97 = 1; _g_boolean_var_97
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "callback != NULL"); return; } } while
(0)
;
1785 g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_98
= 0; if (!cancellable || (((__extension__ ({ GTypeInstance *
__inst = (GTypeInstance*) ((cancellable)); GType __t = ((g_cancellable_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_98 = 1; _g_boolean_var_98; }), 1)
)) { } else { g_return_if_fail_warning ("CdkPixbuf", ((const char
*) (__func__)), "!cancellable || G_IS_CANCELLABLE (cancellable)"
); return; } } while (0)
;
1786
1787 data = g_slice_new (AtScaleData)((AtScaleData*) g_slice_alloc ((sizeof (AtScaleData) > 0 ?
sizeof (AtScaleData) : 1)))
;
1788 data->width = width;
1789 data->height = height;
1790 data->preserve_aspect_ratio = preserve_aspect_ratio;
1791
1792 loader = cdk_pixbuf_loader_new ();
1793 g_signal_connect (loader, "size-prepared",g_signal_connect_data ((loader), ("size-prepared"), (((GCallback
) (at_scale_size_prepared_cb))), (data), ((void*)0), (GConnectFlags
) 0)
1794 G_CALLBACK (at_scale_size_prepared_cb), data)g_signal_connect_data ((loader), ("size-prepared"), (((GCallback
) (at_scale_size_prepared_cb))), (data), ((void*)0), (GConnectFlags
) 0)
;
1795 g_object_set_data_full (G_OBJECT (loader)((((GObject*) (void *) ((loader))))),
1796 "cdk-pixbuf-please-kill-me-later",
1797 data,
1798 (GDestroyNotify) at_scale_data_async_data_free);
1799
1800 task = g_task_new (stream, cancellable, callback, user_data);
1801 g_task_set_source_tag (task, cdk_pixbuf_new_from_stream_at_scale_async)do { GTask *_task = (task); (g_task_set_source_tag) (_task, cdk_pixbuf_new_from_stream_at_scale_async
); if (g_task_get_name (_task) == ((void*)0)) g_task_set_static_name
(_task, "cdk_pixbuf_new_from_stream_at_scale_async"); } while
(0)
;
1802 g_task_set_task_data (task, loader, g_object_unref);
1803
1804 g_input_stream_read_bytes_async (stream,
1805 LOAD_BUFFER_SIZE65536,
1806 G_PRIORITY_DEFAULT0,
1807 cancellable,
1808 load_from_stream_async_cb,
1809 task);
1810}
1811
1812/**
1813 * cdk_pixbuf_new_from_stream:
1814 * @stream: a `GInputStream` to load the pixbuf from
1815 * @cancellable: (allow-none): optional `GCancellable` object, `NULL` to ignore
1816 * @error: Return location for an error
1817 *
1818 * Creates a new pixbuf by loading an image from an input stream.
1819 *
1820 * The file format is detected automatically.
1821 *
1822 * If `NULL` is returned, then `error` will be set.
1823 *
1824 * The `cancellable` can be used to abort the operation from another thread.
1825 * If the operation was cancelled, the error `G_IO_ERROR_CANCELLED` will be
1826 * returned. Other possible errors are in the `CDK_PIXBUF_ERROR` and
1827 * `G_IO_ERROR` domains.
1828 *
1829 * The stream is not closed.
1830 *
1831 * Returns: (nullable): A newly-created pixbuf
1832 *
1833 * Since: 2.14
1834 **/
1835CdkPixbuf *
1836cdk_pixbuf_new_from_stream (GInputStream *stream,
1837 GCancellable *cancellable,
1838 GError **error)
1839{
1840 CdkPixbuf *pixbuf;
1841 CdkPixbufLoader *loader;
1842
1843 loader = cdk_pixbuf_loader_new ();
1844 pixbuf = load_from_stream (loader, stream, cancellable, error);
1845 g_object_unref (loader);
1846
1847 return pixbuf;
1848}
1849
1850CdkPixbuf *
1851_cdk_pixbuf_new_from_resource_try_pixdata (const char *resource_path)
1852{
1853 gsize data_size;
1854 GBytes *bytes;
1855
1856G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
1857 /* We specialize CdkPixdata files, making these a reference to the
1858 * compiled-in resource data, whether uncompressed and mmap'ed, or
1859 * compressed, and uncompressed on-the-fly.
1860 */
1861 if (g_resources_get_info (resource_path, 0, &data_size, NULL((void*)0), NULL((void*)0)) &&
1862 data_size > sizeof (guint32) &&
1863 (bytes = g_resources_lookup_data (resource_path, 0, NULL((void*)0))) != NULL((void*)0)) {
1864 CdkPixbuf *pixbuf = NULL((void*)0);
1865 const guint8 *stream = g_bytes_get_data (bytes, NULL((void*)0));
1866 CdkPixdata pixdata;
1867 guint32 magic;
1868
1869 magic = ((guint32) stream[0] << 24)
1870 + ((guint32) stream[1] << 16)
1871 + ((guint32) stream[2] << 8)
1872 + (guint32) stream[3];
1873 if (magic == CDK_PIXBUF_MAGIC_NUMBER(0x47646b50) &&
1874 cdk_pixdata_deserialize (&pixdata, data_size, stream, NULL((void*)0))) {
1875 pixbuf = cdk_pixbuf_from_pixdata (&pixdata, FALSE(0), NULL((void*)0));
1876 }
1877
1878 if (pixbuf) {
1879 /* Free the GBytes with the pixbuf */
1880 g_object_set_data_full (G_OBJECT (pixbuf)((((GObject*) (void *) ((pixbuf))))), "cdk-pixbuf-resource-bytes", bytes, (GDestroyNotify) g_bytes_unref);
1881 return pixbuf;
1882 } else {
1883 g_bytes_unref (bytes);
1884 }
1885 }
1886G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop
1887
1888 return NULL((void*)0);
1889}
1890
1891/**
1892 * cdk_pixbuf_new_from_resource: (constructor)
1893 * @resource_path: the path of the resource file
1894 * @error: Return location for an error
1895 *
1896 * Creates a new pixbuf by loading an image from an resource.
1897 *
1898 * The file format is detected automatically. If `NULL` is returned, then
1899 * @error will be set.
1900 *
1901 * Returns: (nullable): A newly-created pixbuf
1902 *
1903 * Since: 2.26
1904 **/
1905CdkPixbuf *
1906cdk_pixbuf_new_from_resource (const gchar *resource_path,
1907 GError **error)
1908{
1909 GInputStream *stream;
1910 CdkPixbuf *pixbuf;
1911
1912 pixbuf = _cdk_pixbuf_new_from_resource_try_pixdata (resource_path);
1913 if (pixbuf)
1914 return pixbuf;
1915
1916 stream = g_resources_open_stream (resource_path, 0, error);
1917 if (stream == NULL((void*)0))
1918 return NULL((void*)0);
1919
1920 pixbuf = cdk_pixbuf_new_from_stream (stream, NULL((void*)0), error);
1921 g_object_unref (stream);
1922 return pixbuf;
1923}
1924
1925/**
1926 * cdk_pixbuf_new_from_resource_at_scale: (constructor)
1927 * @resource_path: the path of the resource file
1928 * @width: The width the image should have or -1 to not constrain the width
1929 * @height: The height the image should have or -1 to not constrain the height
1930 * @preserve_aspect_ratio: `TRUE` to preserve the image's aspect ratio
1931 * @error: Return location for an error
1932 *
1933 * Creates a new pixbuf by loading an image from an resource.
1934 *
1935 * The file format is detected automatically. If `NULL` is returned, then
1936 * @error will be set.
1937 *
1938 * The image will be scaled to fit in the requested size, optionally
1939 * preserving the image's aspect ratio. When preserving the aspect ratio,
1940 * a @width of -1 will cause the image to be scaled to the exact given
1941 * height, and a @height of -1 will cause the image to be scaled to the
1942 * exact given width. When not preserving aspect ratio, a @width or
1943 * @height of -1 means to not scale the image at all in that dimension.
1944 *
1945 * The stream is not closed.
1946 *
1947 * Returns: (nullable): A newly-created pixbuf
1948 *
1949 * Since: 2.26
1950 */
1951CdkPixbuf *
1952cdk_pixbuf_new_from_resource_at_scale (const char *resource_path,
1953 int width,
1954 int height,
1955 gboolean preserve_aspect_ratio,
1956 GError **error)
1957{
1958 GInputStream *stream;
1959 CdkPixbuf *pixbuf;
1960
1961 stream = g_resources_open_stream (resource_path, 0, error);
1962 if (stream == NULL((void*)0))
1963 return NULL((void*)0);
1964
1965 pixbuf = cdk_pixbuf_new_from_stream_at_scale (stream, width, height, preserve_aspect_ratio, NULL((void*)0), error);
1966 g_object_unref (stream);
1967 return pixbuf;
1968}
1969
1970/**
1971 * cdk_pixbuf_new_from_stream_async: (finish-func cdk_pixbuf_new_from_stream_finish)
1972 * @stream: a `GInputStream` from which to load the pixbuf
1973 * @cancellable: (nullable): optional `GCancellable` object, `NULL` to ignore
1974 * @callback: (scope async) (closure user_data): a `GAsyncReadyCallback` to call when the pixbuf is loaded
1975 * @user_data: the data to pass to the callback function
1976 *
1977 * Creates a new pixbuf by asynchronously loading an image from an input stream.
1978 *
1979 * For more details see cdk_pixbuf_new_from_stream(), which is the synchronous
1980 * version of this function.
1981 *
1982 * When the operation is finished, @callback will be called in the main thread.
1983 * You can then call cdk_pixbuf_new_from_stream_finish() to get the result of
1984 * the operation.
1985 *
1986 * Since: 2.24
1987 **/
1988void
1989cdk_pixbuf_new_from_stream_async (GInputStream *stream,
1990 GCancellable *cancellable,
1991 GAsyncReadyCallback callback,
1992 gpointer user_data)
1993{
1994 GTask *task;
1995
1996 g_return_if_fail (G_IS_INPUT_STREAM (stream))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_99
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stream)); GType __t = ((g_input_stream_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_99
= 1; _g_boolean_var_99; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "G_IS_INPUT_STREAM (stream)"
); return; } } while (0)
;
1997 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_100
= 0; if (callback != ((void*)0)) _g_boolean_var_100 = 1; _g_boolean_var_100
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "callback != NULL"); return; } } while
(0)
;
1998 g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_101
= 0; if (!cancellable || (((__extension__ ({ GTypeInstance *
__inst = (GTypeInstance*) ((cancellable)); GType __t = ((g_cancellable_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_101 = 1; _g_boolean_var_101; }), 1
))) { } else { g_return_if_fail_warning ("CdkPixbuf", ((const
char*) (__func__)), "!cancellable || G_IS_CANCELLABLE (cancellable)"
); return; } } while (0)
;
1999
2000 task = g_task_new (stream, cancellable, callback, user_data);
2001 g_task_set_source_tag (task, cdk_pixbuf_new_from_stream_async)do { GTask *_task = (task); (g_task_set_source_tag) (_task, cdk_pixbuf_new_from_stream_async
); if (g_task_get_name (_task) == ((void*)0)) g_task_set_static_name
(_task, "cdk_pixbuf_new_from_stream_async"); } while (0)
;
2002 g_task_set_task_data (task, cdk_pixbuf_loader_new (), g_object_unref);
2003
2004 g_input_stream_read_bytes_async (stream,
2005 LOAD_BUFFER_SIZE65536,
2006 G_PRIORITY_DEFAULT0,
2007 cancellable,
2008 load_from_stream_async_cb,
2009 task);
2010}
2011
2012/**
2013 * cdk_pixbuf_new_from_stream_finish: (constructor)
2014 * @async_result: a `GAsyncResult`
2015 * @error: a `GError`, or `NULL`
2016 *
2017 * Finishes an asynchronous pixbuf creation operation started with
2018 * cdk_pixbuf_new_from_stream_async().
2019 *
2020 * Returns: (nullable): the newly created pixbuf
2021 *
2022 * Since: 2.24
2023 **/
2024CdkPixbuf *
2025cdk_pixbuf_new_from_stream_finish (GAsyncResult *async_result,
2026 GError **error)
2027{
2028 GTask *task;
2029
2030 g_return_val_if_fail (G_IS_TASK (async_result), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_102
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((async_result)); GType __t = ((g_task_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_102
= 1; _g_boolean_var_102; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "G_IS_TASK (async_result)"
); return (((void*)0)); } } while (0)
;
2031 g_return_val_if_fail (!error || (error && !*error), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_103
= 0; if (!error || (error && !*error)) _g_boolean_var_103
= 1; _g_boolean_var_103; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "!error || (error && !*error)"
); return (((void*)0)); } } while (0)
;
2032
2033 task = G_TASK (async_result)((((GTask*) (void *) ((async_result)))));
2034
2035 g_warn_if_fail (g_task_get_source_tag (task) == cdk_pixbuf_new_from_stream_async ||do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_104
= 0; if (g_task_get_source_tag (task) == cdk_pixbuf_new_from_stream_async
|| g_task_get_source_tag (task) == cdk_pixbuf_new_from_stream_at_scale_async
) _g_boolean_var_104 = 1; _g_boolean_var_104; }), 1)) ; else g_warn_message
("CdkPixbuf", "../cdk-pixbuf/cdk-pixbuf-io.c", 2036, ((const
char*) (__func__)), "g_task_get_source_tag (task) == cdk_pixbuf_new_from_stream_async || g_task_get_source_tag (task) == cdk_pixbuf_new_from_stream_at_scale_async"
); } while (0)
2036 g_task_get_source_tag (task) == cdk_pixbuf_new_from_stream_at_scale_async)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_104
= 0; if (g_task_get_source_tag (task) == cdk_pixbuf_new_from_stream_async
|| g_task_get_source_tag (task) == cdk_pixbuf_new_from_stream_at_scale_async
) _g_boolean_var_104 = 1; _g_boolean_var_104; }), 1)) ; else g_warn_message
("CdkPixbuf", "../cdk-pixbuf/cdk-pixbuf-io.c", 2036, ((const
char*) (__func__)), "g_task_get_source_tag (task) == cdk_pixbuf_new_from_stream_async || g_task_get_source_tag (task) == cdk_pixbuf_new_from_stream_at_scale_async"
); } while (0)
;
2037
2038 return g_task_propagate_pointer (task, error);
2039}
2040
2041static void
2042info_cb (CdkPixbufLoader *loader,
2043 int width,
2044 int height,
2045 gpointer data)
2046{
2047 struct {
2048 CdkPixbufFormat *format;
2049 int width;
2050 int height;
2051 } *info = data;
2052
2053 g_return_if_fail (width > 0 && height > 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_105
= 0; if (width > 0 && height > 0) _g_boolean_var_105
= 1; _g_boolean_var_105; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "width > 0 && height > 0"
); return; } } while (0)
;
2054
2055 info->format = cdk_pixbuf_loader_get_format (loader);
2056 info->width = width;
2057 info->height = height;
2058
2059 cdk_pixbuf_loader_set_size (loader, 0, 0);
2060}
2061
2062/**
2063 * cdk_pixbuf_get_file_info:
2064 * @filename: (type filename): The name of the file to identify.
2065 * @width: (optional) (out): Return location for the width of the image
2066 * @height: (optional) (out): Return location for the height of the image
2067 *
2068 * Parses an image file far enough to determine its format and size.
2069 *
2070 * Returns: (nullable) (transfer none): A `CdkPixbufFormat` describing
2071 * the image format of the file
2072 *
2073 * Since: 2.4
2074 **/
2075CdkPixbufFormat *
2076cdk_pixbuf_get_file_info (const gchar *filename,
2077 gint *width,
2078 gint *height)
2079{
2080 CdkPixbufLoader *loader;
2081 guchar buffer[SNIFF_BUFFER_SIZE4096];
2082 int length;
2083 FILE *f;
2084 struct {
2085 CdkPixbufFormat *format;
2086 gint width;
2087 gint height;
2088 } info;
2089
2090 g_return_val_if_fail (filename != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_106
= 0; if (filename != ((void*)0)) _g_boolean_var_106 = 1; _g_boolean_var_106
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "filename != NULL"); return (((void
*)0)); } } while (0)
;
2091
2092 f = g_fopenfopen (filename, "rb");
2093 if (!f)
2094 return NULL((void*)0);
2095
2096 loader = _cdk_pixbuf_loader_new_with_filename (filename);
2097
2098 info.format = NULL((void*)0);
2099 info.width = -1;
2100 info.height = -1;
2101
2102 g_signal_connect (loader, "size-prepared", G_CALLBACK (info_cb), &info)g_signal_connect_data ((loader), ("size-prepared"), (((GCallback
) (info_cb))), (&info), ((void*)0), (GConnectFlags) 0)
;
2103
2104 while (!feof (f) && !ferror (f)) {
2105 length = fread (buffer, 1, sizeof (buffer), f);
2106 if (length > 0) {
2107 if (!cdk_pixbuf_loader_write (loader, buffer, length, NULL((void*)0)))
2108 break;
2109 }
2110 if (info.format != NULL((void*)0))
2111 break;
2112 }
2113
2114 fclose (f);
2115 cdk_pixbuf_loader_close (loader, NULL((void*)0));
2116 g_object_unref (loader);
2117
2118 if (width)
2119 *width = info.width;
2120 if (height)
2121 *height = info.height;
2122
2123 return info.format;
2124}
2125
2126typedef struct {
2127 gchar *filename;
2128 gint width;
2129 gint height;
2130} GetFileInfoAsyncData;
2131
2132static void
2133get_file_info_async_data_free (GetFileInfoAsyncData *data)
2134{
2135 g_free (data->filename);
2136 g_slice_free (GetFileInfoAsyncData, data)do { if (1) g_slice_free1 (sizeof (GetFileInfoAsyncData), (data
)); else (void) ((GetFileInfoAsyncData*) 0 == (data)); } while
(0)
;
2137}
2138
2139static void
2140get_file_info_thread (GTask *task,
2141 gpointer source_object,
2142 GetFileInfoAsyncData *data,
2143 GCancellable *cancellable)
2144{
2145 CdkPixbufFormat *format;
2146
2147 format = cdk_pixbuf_get_file_info (data->filename, &data->width, &data->height);
2148 if (format == NULL((void*)0)) {
2149 g_task_return_new_error (task,
2150 CDK_PIXBUF_ERRORcdk_pixbuf_error_quark (),
2151 CDK_PIXBUF_ERROR_UNKNOWN_TYPE,
2152 "Failed to recognize image format");
2153 } else {
2154 g_task_return_pointer (task,
2155 cdk_pixbuf_format_copy (format),
2156 (GDestroyNotify) cdk_pixbuf_format_free);
2157 }
2158}
2159
2160/**
2161 * cdk_pixbuf_get_file_info_async:
2162 * @filename: (type filename): The name of the file to identify
2163 * @cancellable: (allow-none): optional `GCancellable` object, `NULL` to ignore
2164 * @callback: a `GAsyncReadyCallback` to call when the file info is available
2165 * @user_data: the data to pass to the callback function
2166 *
2167 * Asynchronously parses an image file far enough to determine its
2168 * format and size.
2169 *
2170 * For more details see cdk_pixbuf_get_file_info(), which is the synchronous
2171 * version of this function.
2172 *
2173 * When the operation is finished, @callback will be called in the
2174 * main thread. You can then call cdk_pixbuf_get_file_info_finish() to
2175 * get the result of the operation.
2176 *
2177 * Since: 2.32
2178 **/
2179void
2180cdk_pixbuf_get_file_info_async (const gchar *filename,
2181 GCancellable *cancellable,
2182 GAsyncReadyCallback callback,
2183 gpointer user_data)
2184{
2185 GetFileInfoAsyncData *data;
2186 GTask *task;
2187
2188 g_return_if_fail (filename != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_107
= 0; if (filename != ((void*)0)) _g_boolean_var_107 = 1; _g_boolean_var_107
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "filename != NULL"); return; } } while
(0)
;
2189 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_108
= 0; if (callback != ((void*)0)) _g_boolean_var_108 = 1; _g_boolean_var_108
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "callback != NULL"); return; } } while
(0)
;
2190 g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_109
= 0; if (!cancellable || (((__extension__ ({ GTypeInstance *
__inst = (GTypeInstance*) ((cancellable)); GType __t = ((g_cancellable_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_109 = 1; _g_boolean_var_109; }), 1
))) { } else { g_return_if_fail_warning ("CdkPixbuf", ((const
char*) (__func__)), "!cancellable || G_IS_CANCELLABLE (cancellable)"
); return; } } while (0)
;
2191
2192 data = g_slice_new0 (GetFileInfoAsyncData)(GetFileInfoAsyncData *) (__extension__ ({ gsize __s = (sizeof
(GetFileInfoAsyncData) > 0 ? sizeof (GetFileInfoAsyncData
) : 1); gpointer __p; __p = g_slice_alloc (__s); memset (__p,
0, __s); __p; }))
;
2193 data->filename = g_strdup (filename)g_strdup_inline (filename);
2194
2195 task = g_task_new (NULL((void*)0), cancellable, callback, user_data);
2196 g_task_set_return_on_cancel (task, TRUE(!(0)));
2197 g_task_set_source_tag (task, cdk_pixbuf_get_file_info_async)do { GTask *_task = (task); (g_task_set_source_tag) (_task, cdk_pixbuf_get_file_info_async
); if (g_task_get_name (_task) == ((void*)0)) g_task_set_static_name
(_task, "cdk_pixbuf_get_file_info_async"); } while (0)
;
2198 g_task_set_task_data (task, data, (GDestroyNotify) get_file_info_async_data_free);
2199 g_task_run_in_thread (task, (GTaskThreadFunc) get_file_info_thread);
2200 g_object_unref (task);
2201}
2202
2203/**
2204 * cdk_pixbuf_get_file_info_finish:
2205 * @async_result: a `GAsyncResult`
2206 * @width: (out): Return location for the width of the image, or `NULL`
2207 * @height: (out): Return location for the height of the image, or `NULL`
2208 * @error: a `GError`, or `NULL`
2209 *
2210 * Finishes an asynchronous pixbuf parsing operation started with
2211 * cdk_pixbuf_get_file_info_async().
2212 *
2213 * Returns: (transfer none) (nullable): A `CdkPixbufFormat` describing the
2214 * image format of the file
2215 *
2216 * Since: 2.32
2217 **/
2218CdkPixbufFormat *
2219cdk_pixbuf_get_file_info_finish (GAsyncResult *async_result,
2220 gint *width,
2221 gint *height,
2222 GError **error)
2223{
2224 GetFileInfoAsyncData *data;
2225 GTask *task;
2226
2227 g_return_val_if_fail (g_task_is_valid (async_result, NULL), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_110
= 0; if (g_task_is_valid (async_result, ((void*)0))) _g_boolean_var_110
= 1; _g_boolean_var_110; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "g_task_is_valid (async_result, NULL)"
); return (((void*)0)); } } while (0)
;
2228
2229 task = G_TASK (async_result)((((GTask*) (void *) ((async_result)))));
2230
2231 g_return_val_if_fail (!error || (error && !*error), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_111
= 0; if (!error || (error && !*error)) _g_boolean_var_111
= 1; _g_boolean_var_111; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "!error || (error && !*error)"
); return (((void*)0)); } } while (0)
;
2232 g_warn_if_fail (g_task_get_source_tag (task) == cdk_pixbuf_get_file_info_async)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_112
= 0; if (g_task_get_source_tag (task) == cdk_pixbuf_get_file_info_async
) _g_boolean_var_112 = 1; _g_boolean_var_112; }), 1)) ; else g_warn_message
("CdkPixbuf", "../cdk-pixbuf/cdk-pixbuf-io.c", 2232, ((const
char*) (__func__)), "g_task_get_source_tag (task) == cdk_pixbuf_get_file_info_async"
); } while (0)
;
2233
2234 data = g_task_get_task_data (task);
2235
2236 if (!g_task_had_error (task)) {
2237 if (width)
2238 *width = data->width;
2239 if (height)
2240 *height = data->height;
2241 }
2242
2243 return g_task_propagate_pointer (task, error);
2244}
2245
2246/**
2247 * cdk_pixbuf_new_from_xpm_data: (constructor)
2248 * @data: (array zero-terminated=1): Pointer to inline XPM data.
2249 *
2250 * Creates a new pixbuf by parsing XPM data in memory.
2251 *
2252 * This data is commonly the result of including an XPM file into a
2253 * program's C source.
2254 *
2255 * Returns: (nullable): A newly-created pixbuf
2256 *
2257 * Deprecated: 2.44: Use [ctor@CdkPixbuf.Pixbuf.new_from_stream] with
2258 * a [class@Gio.MemoryInputStream], making sure to handle errors in
2259 * case the XPM format loader is not available
2260 **/
2261CdkPixbuf *
2262cdk_pixbuf_new_from_xpm_data (const char **data)
2263{
2264 CdkPixbuf *(* load_xpm_data) (const char **data);
2265 CdkPixbuf *pixbuf;
2266 GError *error = NULL((void*)0);
2267 CdkPixbufModule *xpm_module;
2268
2269 g_return_val_if_fail (data != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_113
= 0; if (data != ((void*)0)) _g_boolean_var_113 = 1; _g_boolean_var_113
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "data != NULL"); return (((void*)0
)); } } while (0)
;
2270
2271 xpm_module = _cdk_pixbuf_get_named_module ("xpm", &error);
2272 if (xpm_module == NULL((void*)0)) {
2273 g_warning ("Error loading XPM image loader: %s", error->message);
2274 g_error_free (error);
2275 return NULL((void*)0);
2276 }
2277
2278 if (!_cdk_pixbuf_load_module (xpm_module, &error)) {
2279 g_warning ("Error loading XPM image loader: %s", error->message);
2280 g_error_free (error);
2281 return NULL((void*)0);
2282 }
2283
2284 if (xpm_module->load_xpm_data == NULL((void*)0)) {
2285 g_warning ("cdk-pixbuf XPM module lacks XPM data capability");
2286 pixbuf = NULL((void*)0);
2287 } else {
2288 load_xpm_data = xpm_module->load_xpm_data;
2289 pixbuf = (* load_xpm_data) (data);
2290 }
2291
2292 return pixbuf;
2293}
2294
2295static void
2296collect_save_options (va_list opts,
2297 gchar ***keys,
2298 gchar ***vals)
2299{
2300 gchar *key;
2301 gchar *val;
2302 gchar *next;
2303 gint count;
2304
2305 count = 0;
2306 *keys = NULL((void*)0);
2307 *vals = NULL((void*)0);
2308
2309 next = va_arg (opts, gchar*)__builtin_va_arg(opts, gchar*);
2310 while (next)
2311 {
2312 key = next;
2313 val = va_arg (opts, gchar*)__builtin_va_arg(opts, gchar*);
2314
2315 ++count;
2316
2317 /* woo, slow */
2318 *keys = g_realloc (*keys, sizeof(gchar*) * (count + 1));
2319 *vals = g_realloc (*vals, sizeof(gchar*) * (count + 1));
2320
2321 (*keys)[count-1] = g_strdup (key)g_strdup_inline (key);
2322 (*vals)[count-1] = g_strdup (val)g_strdup_inline (val);
2323
2324 (*keys)[count] = NULL((void*)0);
2325 (*vals)[count] = NULL((void*)0);
2326
2327 next = va_arg (opts, gchar*)__builtin_va_arg(opts, gchar*);
2328 }
2329}
2330
2331static gboolean
2332save_to_file_callback (const gchar *buf,
2333 gsize count,
2334 GError **error,
2335 gpointer data)
2336{
2337 FILE *filehandle = data;
2338 gsize n;
2339
2340 n = fwrite (buf, 1, count, filehandle);
2341 if (n != count) {
2342 gint save_errno = errno(*__errno_location ());
2343 g_set_error (error,
2344 G_FILE_ERRORg_file_error_quark (),
2345 g_file_error_from_errno (save_errno),
2346 _("Error writing to image file: %s")((char *) g_dgettext ("cdk-pixbuf", "Error writing to image file: %s"
))
,
2347 g_strerror (save_errno));
2348 return FALSE(0);
2349 }
2350 return TRUE(!(0));
2351}
2352
2353static gboolean
2354cdk_pixbuf_real_save (CdkPixbuf *pixbuf,
2355 FILE *filehandle,
2356 const char *type,
2357 gchar **keys,
2358 gchar **values,
2359 GError **error)
2360{
2361 gboolean ret;
2362 CdkPixbufModule *image_module = NULL((void*)0);
2363
2364 image_module = _cdk_pixbuf_get_named_module (type, error);
2365
2366 if (image_module == NULL((void*)0))
2367 return FALSE(0);
2368
2369 if (!_cdk_pixbuf_load_module (image_module, error))
2370 return FALSE(0);
2371
2372 if (image_module->save) {
2373 /* save normally */
2374 ret = (* image_module->save) (filehandle, pixbuf,
2375 keys, values,
2376 error);
2377 } else if (image_module->save_to_callback) {
2378 /* save with simple callback */
2379 ret = (* image_module->save_to_callback) (save_to_file_callback,
2380 filehandle, pixbuf,
2381 keys, values,
2382 error);
2383 } else {
2384 /* can't save */
2385 g_set_error (error,
2386 CDK_PIXBUF_ERRORcdk_pixbuf_error_quark (),
2387 CDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
2388 _("This build of cdk-pixbuf does not support saving the image format: %s")((char *) g_dgettext ("cdk-pixbuf", "This build of cdk-pixbuf does not support saving the image format: %s"
))
,
2389 type);
2390 ret = FALSE(0);
2391 }
2392
2393 return ret;
2394}
2395
2396#define TMP_FILE_BUF_SIZE4096 4096
2397
2398static gboolean
2399save_to_callback_with_tmp_file (CdkPixbufModule *image_module,
2400 CdkPixbuf *pixbuf,
2401 CdkPixbufSaveFunc save_func,
2402 gpointer user_data,
2403 gchar **keys,
2404 gchar **values,
2405 GError **error)
2406{
2407 int fd;
2408 FILE *f = NULL((void*)0);
2409 gboolean retval = FALSE(0);
2410 gchar *buf = NULL((void*)0);
2411 gsize n;
2412 gchar *filename = NULL((void*)0);
2413
2414 buf = g_try_malloc (TMP_FILE_BUF_SIZE4096);
2415 if (buf == NULL((void*)0)) {
2416 g_set_error_literal (error,
2417 CDK_PIXBUF_ERRORcdk_pixbuf_error_quark (),
2418 CDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
2419 _("Insufficient memory to save image to callback")((char *) g_dgettext ("cdk-pixbuf", "Insufficient memory to save image to callback"
))
);
2420 goto end;
2421 }
2422
2423 fd = g_file_open_tmp ("cdkpixbuf-save-tmp.XXXXXX", &filename, error);
2424 if (fd == -1)
2425 goto end;
2426 f = fdopen (fd, "wb+");
2427 if (f == NULL((void*)0)) {
2428 gint save_errno = errno(*__errno_location ());
2429 g_set_error_literal (error,
2430 G_FILE_ERRORg_file_error_quark (),
2431 g_file_error_from_errno (save_errno),
2432 _("Failed to open temporary file")((char *) g_dgettext ("cdk-pixbuf", "Failed to open temporary file"
))
);
2433 goto end;
2434 }
2435
2436 retval = (image_module->save) (f, pixbuf, keys, values, error);
2437 if (!retval)
2438 goto end;
2439
2440 rewind (f);
2441 for (;;) {
2442 n = fread (buf, 1, TMP_FILE_BUF_SIZE4096, f);
2443 if (n > 0) {
2444 if (!save_func (buf, n, error, user_data))
2445 goto end;
2446 }
2447 if (n != TMP_FILE_BUF_SIZE4096)
2448 break;
2449 }
2450 if (ferror (f)) {
2451 gint save_errno = errno(*__errno_location ());
2452 g_set_error_literal (error,
2453 G_FILE_ERRORg_file_error_quark (),
2454 g_file_error_from_errno (save_errno),
2455 _("Failed to read from temporary file")((char *) g_dgettext ("cdk-pixbuf", "Failed to read from temporary file"
))
);
2456 goto end;
2457 }
2458 retval = TRUE(!(0));
2459
2460 end:
2461 /* cleanup and return retval */
2462 if (f)
2463 fclose (f);
2464 if (filename) {
2465 g_unlink (filename);
2466 g_free (filename);
2467 }
2468 g_free (buf);
2469
2470 return retval;
2471}
2472
2473static gboolean
2474cdk_pixbuf_real_save_to_callback (CdkPixbuf *pixbuf,
2475 CdkPixbufSaveFunc save_func,
2476 gpointer user_data,
2477 const char *type,
2478 gchar **keys,
2479 gchar **values,
2480 GError **error)
2481{
2482 gboolean ret;
2483 CdkPixbufModule *image_module = NULL((void*)0);
2484
2485 image_module = _cdk_pixbuf_get_named_module (type, error);
2486
2487 if (image_module == NULL((void*)0))
2488 return FALSE(0);
2489
2490 if (!_cdk_pixbuf_load_module (image_module, error))
2491 return FALSE(0);
2492
2493 if (image_module->save_to_callback) {
2494 /* save normally */
2495 ret = (* image_module->save_to_callback) (save_func, user_data,
2496 pixbuf, keys, values,
2497 error);
2498 } else if (image_module->save) {
2499 /* use a temporary file */
2500 ret = save_to_callback_with_tmp_file (image_module, pixbuf,
2501 save_func, user_data,
2502 keys, values,
2503 error);
2504 } else {
2505 /* can't save */
2506 g_set_error (error,
2507 CDK_PIXBUF_ERRORcdk_pixbuf_error_quark (),
2508 CDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
2509 _("This build of cdk-pixbuf does not support saving the image format: %s")((char *) g_dgettext ("cdk-pixbuf", "This build of cdk-pixbuf does not support saving the image format: %s"
))
,
2510 type);
2511 ret = FALSE(0);
2512 }
2513
2514 return ret;
2515}
2516
2517
2518/**
2519 * cdk_pixbuf_save:
2520 * @pixbuf: a `CdkPixbuf`.
2521 * @filename: (type filename): name of file to save.
2522 * @type: name of file format.
2523 * @error: (nullable): return location for error
2524 * @...: list of key-value save options, followed by `NULL`
2525 *
2526 * Saves pixbuf to a file in format @type. By default, "jpeg", "png", "ico"
2527 * and "bmp" are possible file formats to save in, but more formats may be
2528 * installed. The list of all writable formats can be determined in the
2529 * following way:
2530 *
2531 * ```c
2532 * void add_if_writable (CdkPixbufFormat *data, GSList **list)
2533 * {
2534 * if (cdk_pixbuf_format_is_writable (data))
2535 * *list = g_slist_prepend (*list, data);
2536 * }
2537 *
2538 * GSList *formats = cdk_pixbuf_get_formats ();
2539 * GSList *writable_formats = NULL;
2540 * g_slist_foreach (formats, add_if_writable, &writable_formats);
2541 * g_slist_free (formats);
2542 * ```
2543 *
2544 * If `error` is set, `FALSE` will be returned. Possible errors include
2545 * those in the `CDK_PIXBUF_ERROR` domain and those in the `G_FILE_ERROR`
2546 * domain.
2547 *
2548 * The variable argument list should be `NULL`-terminated; if not empty,
2549 * it should contain pairs of strings that modify the save
2550 * parameters. For example:
2551 *
2552 * ```c
2553 * cdk_pixbuf_save (pixbuf, handle, "jpeg", &error, "quality", "100", NULL);
2554 * ```
2555 *
2556 * Currently only few parameters exist.
2557 *
2558 * JPEG images can be saved with a "quality" parameter; its value should be
2559 * in the range `[0, 100]`. JPEG and PNG density can be set by setting the
2560 * "x-dpi" and "y-dpi" parameters to the appropriate values in dots per inch.
2561 *
2562 * Text chunks can be attached to PNG images by specifying parameters of
2563 * the form "tEXt::key", where key is an ASCII string of length 1-79.
2564 * The values are UTF-8 encoded strings. The PNG compression level can
2565 * be specified using the "compression" parameter; it's value is in an
2566 * integer in the range of `[0, 9]`.
2567 *
2568 * ICC color profiles can also be embedded into PNG, JPEG and TIFF images.
2569 * The "icc-profile" value should be the complete ICC profile encoded
2570 * into base64.
2571 *
2572 * ```c
2573 * char *contents;
2574 * gsize length;
2575 *
2576 * // icm_path is set elsewhere
2577 * g_file_get_contents (icm_path, &contents, &length, NULL);
2578 *
2579 * char *contents_encode = g_base64_encode ((const guchar *) contents, length);
2580 *
2581 * cdk_pixbuf_save (pixbuf, handle, "png", &error, "icc-profile", contents_encode, NULL);
2582 * ```
2583 *
2584 * TIFF images recognize:
2585 *
2586 * 1. a "bits-per-sample" option (integer) which can be either 1 for saving
2587 * bi-level CCITTFAX4 images, or 8 for saving 8-bits per sample
2588 * 2. a "compression" option (integer) which can be 1 for no compression,
2589 * 2 for Huffman, 5 for LZW, 7 for JPEG and 8 for DEFLATE (see the libtiff
2590 * documentation and tiff.h for all supported codec values)
2591 * 3. an "icc-profile" option (zero-terminated string) containing a base64
2592 * encoded ICC color profile.
2593 *
2594 * ICO images can be saved in depth 16, 24, or 32, by using the "depth"
2595 * parameter. When the ICO saver is given "x_hot" and "y_hot" parameters,
2596 * it produces a CUR instead of an ICO.
2597 *
2598 * Returns: `TRUE` on success, and `FALSE` otherwise
2599 **/
2600gboolean
2601cdk_pixbuf_save (CdkPixbuf *pixbuf,
2602 const char *filename,
2603 const char *type,
2604 GError **error,
2605 ...)
2606{
2607 gchar **keys = NULL((void*)0);
2608 gchar **values = NULL((void*)0);
2609 va_list args;
2610 gboolean result;
2611
2612 g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_114
= 0; if (error == ((void*)0) || *error == ((void*)0)) _g_boolean_var_114
= 1; _g_boolean_var_114; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "error == NULL || *error == NULL"
); return ((0)); } } while (0)
;
2613
2614 va_start (args, error)__builtin_va_start(args, error);
2615
2616 collect_save_options (args, &keys, &values);
2617
2618 va_end (args)__builtin_va_end(args);
2619
2620 result = cdk_pixbuf_savev (pixbuf, filename, type,
2621 keys, values,
2622 error);
2623
2624 g_strfreev (keys);
2625 g_strfreev (values);
2626
2627 return result;
2628}
2629
2630/**
2631 * cdk_pixbuf_savev:
2632 * @pixbuf: a `CdkPixbuf`.
2633 * @filename: (type filename): name of file to save.
2634 * @type: name of file format.
2635 * @option_keys: (array zero-terminated=1) (element-type utf8) (nullable): name of options to set
2636 * @option_values: (array zero-terminated=1) (element-type utf8) (nullable): values for named options
2637 * @error: (allow-none): return location for error, or `NULL`
2638 *
2639 * Vector version of `cdk_pixbuf_save()`.
2640 *
2641 * Saves pixbuf to a file in `type`, which is currently "jpeg", "png", "tiff", "ico" or "bmp".
2642 *
2643 * If @error is set, `FALSE` will be returned.
2644 *
2645 * See [method@CdkPixbuf.Pixbuf.save] for more details.
2646 *
2647 * Returns: whether an error was set
2648 **/
2649
2650gboolean
2651cdk_pixbuf_savev (CdkPixbuf *pixbuf,
2652 const char *filename,
2653 const char *type,
2654 char **option_keys,
2655 char **option_values,
2656 GError **error)
2657{
2658 FILE *f = NULL((void*)0);
2659 gboolean result;
2660
2661 g_return_val_if_fail (CDK_IS_PIXBUF (pixbuf), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_115
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((pixbuf)); GType __t = ((cdk_pixbuf_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_115
= 1; _g_boolean_var_115; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "CDK_IS_PIXBUF (pixbuf)"
); return ((0)); } } while (0)
;
2662 g_return_val_if_fail (cdk_pixbuf_get_width (pixbuf) >= 0, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_116
= 0; if (cdk_pixbuf_get_width (pixbuf) >= 0) _g_boolean_var_116
= 1; _g_boolean_var_116; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "cdk_pixbuf_get_width (pixbuf) >= 0"
); return ((0)); } } while (0)
;
2663 g_return_val_if_fail (cdk_pixbuf_get_height (pixbuf) >= 0, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_117
= 0; if (cdk_pixbuf_get_height (pixbuf) >= 0) _g_boolean_var_117
= 1; _g_boolean_var_117; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "cdk_pixbuf_get_height (pixbuf) >= 0"
); return ((0)); } } while (0)
;
2664 g_return_val_if_fail (cdk_pixbuf_get_n_channels (pixbuf) >= 0, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_118
= 0; if (cdk_pixbuf_get_n_channels (pixbuf) >= 0) _g_boolean_var_118
= 1; _g_boolean_var_118; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "cdk_pixbuf_get_n_channels (pixbuf) >= 0"
); return ((0)); } } while (0)
;
2665 g_return_val_if_fail (filename != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_119
= 0; if (filename != ((void*)0)) _g_boolean_var_119 = 1; _g_boolean_var_119
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "filename != NULL"); return ((0));
} } while (0)
;
2666 g_return_val_if_fail (type != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_120
= 0; if (type != ((void*)0)) _g_boolean_var_120 = 1; _g_boolean_var_120
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "type != NULL"); return ((0)); } }
while (0)
;
2667 g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_121
= 0; if (error == ((void*)0) || *error == ((void*)0)) _g_boolean_var_121
= 1; _g_boolean_var_121; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "error == NULL || *error == NULL"
); return ((0)); } } while (0)
;
2668
2669 f = g_fopenfopen (filename, "wb");
2670
2671 if (f == NULL((void*)0)) {
2672 gint save_errno = errno(*__errno_location ());
2673 gchar *display_name = g_filename_display_name (filename);
2674 g_set_error (error,
2675 G_FILE_ERRORg_file_error_quark (),
2676 g_file_error_from_errno (save_errno),
2677 _("Failed to open “%s” for writing: %s")((char *) g_dgettext ("cdk-pixbuf", "Failed to open “%s” for writing: %s"
))
,
2678 display_name,
2679 g_strerror (save_errno));
2680 g_free (display_name);
2681 return FALSE(0);
2682 }
2683
2684
2685 result = cdk_pixbuf_real_save (pixbuf, f, type,
2686 option_keys, option_values,
2687 error);
2688
2689
2690 if (!result) {
2691 g_return_val_if_fail (error == NULL || *error != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_122
= 0; if (error == ((void*)0) || *error != ((void*)0)) _g_boolean_var_122
= 1; _g_boolean_var_122; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "error == NULL || *error != NULL"
); return ((0)); } } while (0)
;
2692 fclose (f);
2693 g_unlink (filename);
2694 return FALSE(0);
2695 }
2696
2697 if (fclose (f) < 0) {
2698 gint save_errno = errno(*__errno_location ());
2699 gchar *display_name = g_filename_display_name (filename);
2700 g_set_error (error,
2701 G_FILE_ERRORg_file_error_quark (),
2702 g_file_error_from_errno (save_errno),
2703 _("Failed to close “%s” while writing image, all data may not have been saved: %s")((char *) g_dgettext ("cdk-pixbuf", "Failed to close “%s” while writing image, all data may not have been saved: %s"
))
,
2704 display_name,
2705 g_strerror (save_errno));
2706 g_free (display_name);
2707 return FALSE(0);
2708 }
2709
2710 return TRUE(!(0));
2711}
2712
2713#ifdef G_OS_WIN32
2714
2715/**
2716 * cdk_pixbuf_savev_utf8:
2717 * @pixbuf: a `CdkPixbuf`.
2718 * @filename: name of file to save.
2719 * @type: name of file format.
2720 * @option_keys: (array zero-terminated=1) (element-type utf8) (nullable): name of options to set
2721 * @option_values: (array zero-terminated=1) (element-type utf8) (nullable): values for named options
2722 * @error: (allow-none): return location for error, or `NULL`
2723 *
2724 * Same as cdk_pixbuf_savev()
2725 *
2726 * Returns: whether an error was set
2727 **/
2728gboolean
2729cdk_pixbuf_savev_utf8 (CdkPixbuf *pixbuf,
2730 const char *filename,
2731 const char *type,
2732 char **option_keys,
2733 char **option_values,
2734 GError **error)
2735{
2736 return cdk_pixbuf_savev (pixbuf, filename, type, option_keys,
2737 option_values, error);
2738}
2739
2740#endif
2741
2742/**
2743 * cdk_pixbuf_save_to_callback:
2744 * @pixbuf: a `CdkPixbuf`.
2745 * @save_func: (scope call): a function that is called to save each block of data that
2746 * the save routine generates.
2747 * @user_data: user data to pass to the save function.
2748 * @type: name of file format.
2749 * @error: (allow-none): return location for error, or `NULL`
2750 * @...: list of key-value save options
2751 *
2752 * Saves pixbuf in format `type` by feeding the produced data to a
2753 * callback.
2754 *
2755 * This function can be used when you want to store the image to something
2756 * other than a file, such as an in-memory buffer or a socket.
2757 *
2758 * If @error is set, `FALSE` will be returned. Possible errors
2759 * include those in the `CDK_PIXBUF_ERROR` domain and whatever the save
2760 * function generates.
2761 *
2762 * See [method@CdkPixbuf.Pixbuf.save] for more details.
2763 *
2764 * Returns: whether an error was set
2765 *
2766 * Since: 2.4
2767 **/
2768gboolean
2769cdk_pixbuf_save_to_callback (CdkPixbuf *pixbuf,
2770 CdkPixbufSaveFunc save_func,
2771 gpointer user_data,
2772 const char *type,
2773 GError **error,
2774 ...)
2775{
2776 gchar **keys = NULL((void*)0);
2777 gchar **values = NULL((void*)0);
2778 va_list args;
2779 gboolean result;
2780
2781 g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_123
= 0; if (error == ((void*)0) || *error == ((void*)0)) _g_boolean_var_123
= 1; _g_boolean_var_123; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "error == NULL || *error == NULL"
); return ((0)); } } while (0)
;
2782
2783 va_start (args, error)__builtin_va_start(args, error);
2784
2785 collect_save_options (args, &keys, &values);
2786
2787 va_end (args)__builtin_va_end(args);
2788
2789 result = cdk_pixbuf_save_to_callbackv (pixbuf, save_func, user_data,
2790 type, keys, values,
2791 error);
2792
2793 g_strfreev (keys);
2794 g_strfreev (values);
2795
2796 return result;
2797}
2798
2799/**
2800 * cdk_pixbuf_save_to_callbackv:
2801 * @pixbuf: a `CdkPixbuf`
2802 * @save_func: (scope call) (closure user_data): a function that is called to
2803 * save each block of data that the save routine generates
2804 * @user_data: user data to pass to the save function
2805 * @type: name of file format
2806 * @option_keys: (array zero-terminated=1) (element-type utf8) (nullable): name of options to set
2807 * @option_values: (array zero-terminated=1) (element-type utf8) (nullable): values for named options
2808 * @error: return location for error, or `NULL`
2809 *
2810 * Vector version of `cdk_pixbuf_save_to_callback()`.
2811 *
2812 * Saves pixbuf to a callback in format @type, which is currently "jpeg",
2813 * "png", "tiff", "ico" or "bmp".
2814 *
2815 * If @error is set, `FALSE` will be returned.
2816 *
2817 * See [method@CdkPixbuf.Pixbuf.save_to_callback] for more details.
2818 *
2819 * Returns: whether an error was set
2820 *
2821 * Since: 2.4
2822 **/
2823gboolean
2824cdk_pixbuf_save_to_callbackv (CdkPixbuf *pixbuf,
2825 CdkPixbufSaveFunc save_func,
2826 gpointer user_data,
2827 const char *type,
2828 char **option_keys,
2829 char **option_values,
2830 GError **error)
2831{
2832 gboolean result;
2833
2834 g_return_val_if_fail (CDK_IS_PIXBUF (pixbuf), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_124
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((pixbuf)); GType __t = ((cdk_pixbuf_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_124
= 1; _g_boolean_var_124; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "CDK_IS_PIXBUF (pixbuf)"
); return ((0)); } } while (0)
;
2835 g_return_val_if_fail (cdk_pixbuf_get_width (pixbuf) >= 0, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_125
= 0; if (cdk_pixbuf_get_width (pixbuf) >= 0) _g_boolean_var_125
= 1; _g_boolean_var_125; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "cdk_pixbuf_get_width (pixbuf) >= 0"
); return ((0)); } } while (0)
;
2836 g_return_val_if_fail (cdk_pixbuf_get_height (pixbuf) >= 0, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_126
= 0; if (cdk_pixbuf_get_height (pixbuf) >= 0) _g_boolean_var_126
= 1; _g_boolean_var_126; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "cdk_pixbuf_get_height (pixbuf) >= 0"
); return ((0)); } } while (0)
;
2837 g_return_val_if_fail (cdk_pixbuf_get_n_channels (pixbuf) >= 0, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_127
= 0; if (cdk_pixbuf_get_n_channels (pixbuf) >= 0) _g_boolean_var_127
= 1; _g_boolean_var_127; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "cdk_pixbuf_get_n_channels (pixbuf) >= 0"
); return ((0)); } } while (0)
;
2838 g_return_val_if_fail (save_func != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_128
= 0; if (save_func != ((void*)0)) _g_boolean_var_128 = 1; _g_boolean_var_128
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "save_func != NULL"); return ((0))
; } } while (0)
;
2839 g_return_val_if_fail (type != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_129
= 0; if (type != ((void*)0)) _g_boolean_var_129 = 1; _g_boolean_var_129
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "type != NULL"); return ((0)); } }
while (0)
;
2840 g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_130
= 0; if (error == ((void*)0) || *error == ((void*)0)) _g_boolean_var_130
= 1; _g_boolean_var_130; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "error == NULL || *error == NULL"
); return ((0)); } } while (0)
;
2841
2842 result = cdk_pixbuf_real_save_to_callback (pixbuf,
2843 save_func, user_data, type,
2844 option_keys, option_values,
2845 error);
2846
2847 if (!result) {
2848 g_return_val_if_fail (error == NULL || *error != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_131
= 0; if (error == ((void*)0) || *error != ((void*)0)) _g_boolean_var_131
= 1; _g_boolean_var_131; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "error == NULL || *error != NULL"
); return ((0)); } } while (0)
;
2849 return FALSE(0);
2850 }
2851
2852 return TRUE(!(0));
2853}
2854
2855/**
2856 * cdk_pixbuf_save_to_buffer:
2857 * @pixbuf: a `CdkPixbuf`.
2858 * @buffer: (array length=buffer_size) (out) (element-type guint8): location to receive a pointer
2859 * to the new buffer.
2860 * @buffer_size: location to receive the size of the new buffer.
2861 * @type: name of file format.
2862 * @error: return location for error, or `NULL`
2863 * @...: list of key-value save options
2864 *
2865 * Saves pixbuf to a new buffer in format `type`, which is currently "jpeg",
2866 * "png", "tiff", "ico" or "bmp".
2867 *
2868 * This is a convenience function that uses `cdk_pixbuf_save_to_callback()`
2869 * to do the real work.
2870 *
2871 * Note that the buffer is not `NUL`-terminated and may contain embedded `NUL`
2872 * characters.
2873 *
2874 * If @error is set, `FALSE` will be returned and @buffer will be set to
2875 * `NULL`. Possible errors include those in the `CDK_PIXBUF_ERROR`
2876 * domain.
2877 *
2878 * See `cdk_pixbuf_save()` for more details.
2879 *
2880 * Returns: whether an error was set
2881 *
2882 * Since: 2.4
2883 **/
2884gboolean
2885cdk_pixbuf_save_to_buffer (CdkPixbuf *pixbuf,
2886 gchar **buffer,
2887 gsize *buffer_size,
2888 const char *type,
2889 GError **error,
2890 ...)
2891{
2892 gchar **keys = NULL((void*)0);
2893 gchar **values = NULL((void*)0);
2894 va_list args;
2895 gboolean result;
2896
2897 g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_132
= 0; if (error == ((void*)0) || *error == ((void*)0)) _g_boolean_var_132
= 1; _g_boolean_var_132; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "error == NULL || *error == NULL"
); return ((0)); } } while (0)
;
2898
2899 va_start (args, error)__builtin_va_start(args, error);
2900
2901 collect_save_options (args, &keys, &values);
2902
2903 va_end (args)__builtin_va_end(args);
2904
2905 result = cdk_pixbuf_save_to_bufferv (pixbuf, buffer, buffer_size,
2906 type, keys, values,
2907 error);
2908
2909 g_strfreev (keys);
2910 g_strfreev (values);
2911
2912 return result;
2913}
2914
2915struct SaveToBufferData {
2916 gchar *buffer;
2917 gsize len, max;
2918};
2919
2920static gboolean
2921save_to_buffer_callback (const gchar *data,
2922 gsize count,
2923 GError **error,
2924 gpointer user_data)
2925{
2926 struct SaveToBufferData *sdata = user_data;
2927 gchar *new_buffer;
2928 gsize new_max;
2929
2930 if (sdata->len + count > sdata->max) {
2931 new_max = MAX (sdata->max*2, sdata->len + count)(((sdata->max*2) > (sdata->len + count)) ? (sdata->
max*2) : (sdata->len + count))
;
2932 new_buffer = g_try_realloc (sdata->buffer, new_max);
2933 if (!new_buffer) {
2934 g_set_error_literal (error,
2935 CDK_PIXBUF_ERRORcdk_pixbuf_error_quark (),
2936 CDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
2937 _("Insufficient memory to save image into a buffer")((char *) g_dgettext ("cdk-pixbuf", "Insufficient memory to save image into a buffer"
))
);
2938 return FALSE(0);
2939 }
2940 sdata->buffer = new_buffer;
2941 sdata->max = new_max;
2942 }
2943 memcpy (sdata->buffer + sdata->len, data, count);
2944 sdata->len += count;
2945 return TRUE(!(0));
2946}
2947
2948/**
2949 * cdk_pixbuf_save_to_bufferv:
2950 * @pixbuf: a `CdkPixbuf`.
2951 * @buffer: (array length=buffer_size) (out) (element-type guint8):
2952 * location to receive a pointer to the new buffer.
2953 * @buffer_size: location to receive the size of the new buffer.
2954 * @type: name of file format.
2955 * @option_keys: (array zero-terminated=1) (element-type utf8) (nullable): name of options to set
2956 * @option_values: (array zero-terminated=1) (element-type utf8) (nullable): values for named options
2957 * @error: (allow-none): return location for error, or `NULL`
2958 *
2959 * Vector version of `cdk_pixbuf_save_to_buffer()`.
2960 *
2961 * Saves pixbuf to a new buffer in format @type, which is currently "jpeg",
2962 * "tiff", "png", "ico" or "bmp".
2963 *
2964 * See [method@CdkPixbuf.Pixbuf.save_to_buffer] for more details.
2965 *
2966 * Returns: whether an error was set
2967 *
2968 * Since: 2.4
2969 **/
2970gboolean
2971cdk_pixbuf_save_to_bufferv (CdkPixbuf *pixbuf,
2972 gchar **buffer,
2973 gsize *buffer_size,
2974 const char *type,
2975 char **option_keys,
2976 char **option_values,
2977 GError **error)
2978{
2979 static const gint initial_max = 1024;
2980 struct SaveToBufferData sdata;
2981
2982 *buffer = NULL((void*)0);
2983 *buffer_size = 0;
2984
2985 sdata.buffer = g_try_malloc (initial_max);
2986 sdata.max = initial_max;
2987 sdata.len = 0;
2988 if (!sdata.buffer) {
2989 g_set_error_literal (error,
2990 CDK_PIXBUF_ERRORcdk_pixbuf_error_quark (),
2991 CDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
2992 _("Insufficient memory to save image into a buffer")((char *) g_dgettext ("cdk-pixbuf", "Insufficient memory to save image into a buffer"
))
);
2993 return FALSE(0);
2994 }
2995
2996 if (!cdk_pixbuf_save_to_callbackv (pixbuf,
2997 save_to_buffer_callback, &sdata,
2998 type, option_keys, option_values,
2999 error)) {
3000 g_free (sdata.buffer);
3001 return FALSE(0);
3002 }
3003
3004 *buffer = sdata.buffer;
3005 *buffer_size = sdata.len;
3006 return TRUE(!(0));
3007}
3008
3009typedef struct {
3010 GOutputStream *stream;
3011 GCancellable *cancellable;
3012} SaveToStreamData;
3013
3014static gboolean
3015save_to_stream (const gchar *buffer,
3016 gsize count,
3017 GError **error,
3018 gpointer data)
3019{
3020 SaveToStreamData *sdata = (SaveToStreamData *)data;
3021 gsize remaining;
3022 gssize written;
3023 GError *my_error = NULL((void*)0);
3024
3025 remaining = count;
3026 written = 0;
3027 while (remaining > 0) {
3028 buffer += written;
3029 remaining -= written;
3030 written = g_output_stream_write (sdata->stream,
3031 buffer, remaining,
3032 sdata->cancellable,
3033 &my_error);
3034 if (written < 0) {
3035 if (!my_error) {
3036 g_set_error_literal (error,
3037 G_IO_ERRORg_io_error_quark(), 0,
3038 _("Error writing to image stream")((char *) g_dgettext ("cdk-pixbuf", "Error writing to image stream"
))
);
3039 }
3040 else {
3041 g_propagate_error (error, my_error);
3042 }
3043 return FALSE(0);
3044 }
3045 }
3046
3047 return TRUE(!(0));
3048}
3049
3050/**
3051 * cdk_pixbuf_save_to_streamv:
3052 * @pixbuf: a `CdkPixbuf`
3053 * @stream: a `GOutputStream` to save the pixbuf to
3054 * @type: name of file format
3055 * @option_keys: (array zero-terminated=1) (element-type utf8) (nullable): name of options to set
3056 * @option_values: (array zero-terminated=1) (element-type utf8) (nullable): values for named options
3057 * @cancellable: (nullable): optional `GCancellable` object, `NULL` to ignore
3058 * @error: return location for error
3059 *
3060 * Saves `pixbuf` to an output stream.
3061 *
3062 * Supported file formats are currently "jpeg", "tiff", "png", "ico" or
3063 * "bmp".
3064 *
3065 * See [method@CdkPixbuf.Pixbuf.save_to_stream] for more details.
3066 *
3067 * Returns: `TRUE` if the pixbuf was saved successfully, `FALSE` if an
3068 * error was set.
3069 *
3070 * Since: 2.36
3071 */
3072gboolean
3073cdk_pixbuf_save_to_streamv (CdkPixbuf *pixbuf,
3074 GOutputStream *stream,
3075 const char *type,
3076 char **option_keys,
3077 char **option_values,
3078 GCancellable *cancellable,
3079 GError **error)
3080{
3081 SaveToStreamData data;
3082
3083 data.stream = stream;
3084 data.cancellable = cancellable;
3085
3086 return cdk_pixbuf_save_to_callbackv (pixbuf, save_to_stream,
3087 &data, type,
3088 option_keys, option_values,
3089 error);
3090}
3091
3092/**
3093 * cdk_pixbuf_save_to_stream:
3094 * @pixbuf: a `CdkPixbuf`
3095 * @stream: a `GOutputStream` to save the pixbuf to
3096 * @type: name of file format
3097 * @cancellable: (allow-none): optional `GCancellable` object, `NULL` to ignore
3098 * @error: (allow-none): return location for error, or `NULL`
3099 * @...: list of key-value save options
3100 *
3101 * Saves `pixbuf` to an output stream.
3102 *
3103 * Supported file formats are currently "jpeg", "tiff", "png", "ico" or
3104 * "bmp". See `cdk_pixbuf_save_to_buffer()` for more details.
3105 *
3106 * The `cancellable` can be used to abort the operation from another
3107 * thread. If the operation was cancelled, the error `G_IO_ERROR_CANCELLED`
3108 * will be returned. Other possible errors are in the `CDK_PIXBUF_ERROR`
3109 * and `G_IO_ERROR` domains.
3110 *
3111 * The stream is not closed at the end of this call.
3112 *
3113 * Returns: `TRUE` if the pixbuf was saved successfully, `FALSE` if an
3114 * error was set.
3115 *
3116 * Since: 2.14
3117 */
3118gboolean
3119cdk_pixbuf_save_to_stream (CdkPixbuf *pixbuf,
3120 GOutputStream *stream,
3121 const char *type,
3122 GCancellable *cancellable,
3123 GError **error,
3124 ...)
3125{
3126 gboolean res;
3127 gchar **keys = NULL((void*)0);
3128 gchar **values = NULL((void*)0);
3129 va_list args;
3130
3131 va_start (args, error)__builtin_va_start(args, error);
3132 collect_save_options (args, &keys, &values);
3133 va_end (args)__builtin_va_end(args);
3134
3135 res = cdk_pixbuf_save_to_streamv (pixbuf, stream, type,
3136 keys, values,
3137 cancellable, error);
3138
3139 g_strfreev (keys);
3140 g_strfreev (values);
3141
3142 return res;
3143}
3144
3145typedef struct {
3146 GOutputStream *stream;
3147 gchar *type;
3148 gchar **keys;
3149 gchar **values;
3150} SaveToStreamAsyncData;
3151
3152static void
3153save_to_stream_async_data_free (SaveToStreamAsyncData *data)
3154{
3155 if (data->stream)
3156 g_object_unref (data->stream);
3157 g_strfreev (data->keys);
3158 g_strfreev (data->values);
3159 g_free (data->type);
3160 g_slice_free (SaveToStreamAsyncData, data)do { if (1) g_slice_free1 (sizeof (SaveToStreamAsyncData), (data
)); else (void) ((SaveToStreamAsyncData*) 0 == (data)); } while
(0)
;
3161}
3162
3163static void
3164save_to_stream_thread (GTask *task,
3165 CdkPixbuf *pixbuf,
3166 SaveToStreamAsyncData *data,
3167 GCancellable *cancellable)
3168{
3169 SaveToStreamData sync_data;
3170 gboolean retval;
3171 GError *error = NULL((void*)0);
3172
3173 sync_data.stream = data->stream;
3174 sync_data.cancellable = cancellable;
3175
3176 retval = cdk_pixbuf_save_to_callbackv (pixbuf, save_to_stream,
3177 &sync_data, data->type,
3178 data->keys, data->values,
3179 &error);
3180
3181 if (retval == FALSE(0)) {
3182 g_task_return_error (task, error);
3183 } else {
3184 g_task_return_boolean (task, TRUE(!(0)));
3185 }
3186}
3187
3188/**
3189 * cdk_pixbuf_save_to_streamv_async: (finish-func cdk_pixbuf_save_to_stream_finish)
3190 * @pixbuf: a `CdkPixbuf`
3191 * @stream: a `GOutputStream` to which to save the pixbuf
3192 * @type: name of file format
3193 * @option_keys: (array zero-terminated=1) (element-type utf8) (nullable): name of options to set
3194 * @option_values: (array zero-terminated=1) (element-type utf8) (nullable): values for named options
3195 * @cancellable: (allow-none): optional `GCancellable` object, `NULL` to ignore
3196 * @callback: a `GAsyncReadyCallback` to call when the pixbuf is saved
3197 * @user_data: the data to pass to the callback function
3198 *
3199 * Saves `pixbuf` to an output stream asynchronously.
3200 *
3201 * For more details see cdk_pixbuf_save_to_streamv(), which is the synchronous
3202 * version of this function.
3203 *
3204 * When the operation is finished, `callback` will be called in the main thread.
3205 *
3206 * You can then call cdk_pixbuf_save_to_stream_finish() to get the result of
3207 * the operation.
3208 *
3209 * Since: 2.36
3210 **/
3211void
3212cdk_pixbuf_save_to_streamv_async (CdkPixbuf *pixbuf,
3213 GOutputStream *stream,
3214 const gchar *type,
3215 gchar **option_keys,
3216 gchar **option_values,
3217 GCancellable *cancellable,
3218 GAsyncReadyCallback callback,
3219 gpointer user_data)
3220{
3221 GTask *task;
3222 SaveToStreamAsyncData *data;
3223
3224 g_return_if_fail (CDK_IS_PIXBUF (pixbuf))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_133
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((pixbuf)); GType __t = ((cdk_pixbuf_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_133
= 1; _g_boolean_var_133; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "CDK_IS_PIXBUF (pixbuf)"
); return; } } while (0)
;
3225 g_return_if_fail (cdk_pixbuf_get_width (pixbuf) >= 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_134
= 0; if (cdk_pixbuf_get_width (pixbuf) >= 0) _g_boolean_var_134
= 1; _g_boolean_var_134; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "cdk_pixbuf_get_width (pixbuf) >= 0"
); return; } } while (0)
;
3226 g_return_if_fail (cdk_pixbuf_get_height (pixbuf) >= 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_135
= 0; if (cdk_pixbuf_get_height (pixbuf) >= 0) _g_boolean_var_135
= 1; _g_boolean_var_135; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "cdk_pixbuf_get_height (pixbuf) >= 0"
); return; } } while (0)
;
3227 g_return_if_fail (cdk_pixbuf_get_n_channels (pixbuf) >= 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_136
= 0; if (cdk_pixbuf_get_n_channels (pixbuf) >= 0) _g_boolean_var_136
= 1; _g_boolean_var_136; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "cdk_pixbuf_get_n_channels (pixbuf) >= 0"
); return; } } while (0)
;
3228 g_return_if_fail (G_IS_OUTPUT_STREAM (stream))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_137
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stream)); GType __t = ((g_output_stream_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_137
= 1; _g_boolean_var_137; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "G_IS_OUTPUT_STREAM (stream)"
); return; } } while (0)
;
3229 g_return_if_fail (type != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_138
= 0; if (type != ((void*)0)) _g_boolean_var_138 = 1; _g_boolean_var_138
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "type != NULL"); return; } } while
(0)
;
3230 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_139
= 0; if (callback != ((void*)0)) _g_boolean_var_139 = 1; _g_boolean_var_139
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "callback != NULL"); return; } } while
(0)
;
3231 g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_140
= 0; if (!cancellable || (((__extension__ ({ GTypeInstance *
__inst = (GTypeInstance*) ((cancellable)); GType __t = ((g_cancellable_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_140 = 1; _g_boolean_var_140; }), 1
))) { } else { g_return_if_fail_warning ("CdkPixbuf", ((const
char*) (__func__)), "!cancellable || G_IS_CANCELLABLE (cancellable)"
); return; } } while (0)
;
3232
3233 data = g_slice_new (SaveToStreamAsyncData)((SaveToStreamAsyncData*) g_slice_alloc ((sizeof (SaveToStreamAsyncData
) > 0 ? sizeof (SaveToStreamAsyncData) : 1)))
;
3234 data->stream = g_object_ref (stream)((__typeof__ (stream)) (g_object_ref) (stream));
3235 data->type = g_strdup (type)g_strdup_inline (type);
3236 data->keys = g_strdupv (option_keys);
3237 data->values = g_strdupv (option_values);
3238
3239 task = g_task_new (pixbuf, cancellable, callback, user_data);
3240 g_task_set_source_tag (task, cdk_pixbuf_save_to_streamv_async)do { GTask *_task = (task); (g_task_set_source_tag) (_task, cdk_pixbuf_save_to_streamv_async
); if (g_task_get_name (_task) == ((void*)0)) g_task_set_static_name
(_task, "cdk_pixbuf_save_to_streamv_async"); } while (0)
;
3241 g_task_set_task_data (task, data, (GDestroyNotify) save_to_stream_async_data_free);
3242 g_task_run_in_thread (task, (GTaskThreadFunc) save_to_stream_thread);
3243 g_object_unref (task);
3244}
3245
3246/**
3247 * cdk_pixbuf_save_to_stream_async: (finish-func cdk_pixbuf_save_to_stream_finish)
3248 * @pixbuf: a `CdkPixbuf`
3249 * @stream: a `GOutputStream` to which to save the pixbuf
3250 * @type: name of file format
3251 * @cancellable: (allow-none): optional `GCancellable` object, `NULL` to ignore
3252 * @callback: a `GAsyncReadyCallback` to call when the pixbuf is saved
3253 * @user_data: the data to pass to the callback function
3254 * @...: list of key-value save options
3255 *
3256 * Saves `pixbuf` to an output stream asynchronously.
3257 *
3258 * For more details see cdk_pixbuf_save_to_stream(), which is the synchronous
3259 * version of this function.
3260 *
3261 * When the operation is finished, `callback` will be called in the main thread.
3262 *
3263 * You can then call cdk_pixbuf_save_to_stream_finish() to get the result of
3264 * the operation.
3265 *
3266 * Since: 2.24
3267 **/
3268void
3269cdk_pixbuf_save_to_stream_async (CdkPixbuf *pixbuf,
3270 GOutputStream *stream,
3271 const gchar *type,
3272 GCancellable *cancellable,
3273 GAsyncReadyCallback callback,
3274 gpointer user_data,
3275 ...)
3276{
3277 gchar **keys = NULL((void*)0);
3278 gchar **values = NULL((void*)0);
3279 va_list args;
3280
3281 g_return_if_fail (CDK_IS_PIXBUF (pixbuf))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_141
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((pixbuf)); GType __t = ((cdk_pixbuf_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_141
= 1; _g_boolean_var_141; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "CDK_IS_PIXBUF (pixbuf)"
); return; } } while (0)
;
3282 g_return_if_fail (cdk_pixbuf_get_width (pixbuf) >= 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_142
= 0; if (cdk_pixbuf_get_width (pixbuf) >= 0) _g_boolean_var_142
= 1; _g_boolean_var_142; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "cdk_pixbuf_get_width (pixbuf) >= 0"
); return; } } while (0)
;
3283 g_return_if_fail (cdk_pixbuf_get_height (pixbuf) >= 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_143
= 0; if (cdk_pixbuf_get_height (pixbuf) >= 0) _g_boolean_var_143
= 1; _g_boolean_var_143; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "cdk_pixbuf_get_height (pixbuf) >= 0"
); return; } } while (0)
;
3284 g_return_if_fail (cdk_pixbuf_get_n_channels (pixbuf) >= 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_144
= 0; if (cdk_pixbuf_get_n_channels (pixbuf) >= 0) _g_boolean_var_144
= 1; _g_boolean_var_144; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "cdk_pixbuf_get_n_channels (pixbuf) >= 0"
); return; } } while (0)
;
3285 g_return_if_fail (G_IS_OUTPUT_STREAM (stream))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_145
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stream)); GType __t = ((g_output_stream_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_145
= 1; _g_boolean_var_145; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "G_IS_OUTPUT_STREAM (stream)"
); return; } } while (0)
;
3286 g_return_if_fail (type != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_146
= 0; if (type != ((void*)0)) _g_boolean_var_146 = 1; _g_boolean_var_146
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "type != NULL"); return; } } while
(0)
;
3287 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_147
= 0; if (callback != ((void*)0)) _g_boolean_var_147 = 1; _g_boolean_var_147
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "callback != NULL"); return; } } while
(0)
;
3288 g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_148
= 0; if (!cancellable || (((__extension__ ({ GTypeInstance *
__inst = (GTypeInstance*) ((cancellable)); GType __t = ((g_cancellable_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_148 = 1; _g_boolean_var_148; }), 1
))) { } else { g_return_if_fail_warning ("CdkPixbuf", ((const
char*) (__func__)), "!cancellable || G_IS_CANCELLABLE (cancellable)"
); return; } } while (0)
;
3289
3290 va_start (args, user_data)__builtin_va_start(args, user_data);
3291 collect_save_options (args, &keys, &values);
3292 va_end (args)__builtin_va_end(args);
3293
3294 cdk_pixbuf_save_to_streamv_async (pixbuf, stream, type,
3295 keys, values,
3296 cancellable, callback, user_data);
3297 g_strfreev (keys);
3298 g_strfreev (values);
3299}
3300
3301/**
3302 * cdk_pixbuf_save_to_stream_finish:
3303 * @async_result: a `GAsyncResult`
3304 * @error: a `GError`, or `NULL`
3305 *
3306 * Finishes an asynchronous pixbuf save operation started with
3307 * cdk_pixbuf_save_to_stream_async().
3308 *
3309 * Returns: `TRUE` if the pixbuf was saved successfully, `FALSE` if an error was set.
3310 *
3311 * Since: 2.24
3312 **/
3313gboolean
3314cdk_pixbuf_save_to_stream_finish (GAsyncResult *async_result,
3315 GError **error)
3316{
3317 GTask *task;
3318
3319 /* Can not use g_task_is_valid because our GTask has a
3320 * source_object which is not available to us anymore.
3321 */
3322 g_return_val_if_fail (G_IS_TASK (async_result), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_149
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((async_result)); GType __t = ((g_task_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_149
= 1; _g_boolean_var_149; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "G_IS_TASK (async_result)"
); return ((0)); } } while (0)
;
3323
3324 task = G_TASK (async_result)((((GTask*) (void *) ((async_result)))));
3325
3326 g_return_val_if_fail (!error || (error && !*error), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_150
= 0; if (!error || (error && !*error)) _g_boolean_var_150
= 1; _g_boolean_var_150; }), 1))) { } else { g_return_if_fail_warning
("CdkPixbuf", ((const char*) (__func__)), "!error || (error && !*error)"
); return ((0)); } } while (0)
;
3327 g_warn_if_fail (g_task_get_source_tag (task) == cdk_pixbuf_save_to_stream_async ||do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_151
= 0; if (g_task_get_source_tag (task) == cdk_pixbuf_save_to_stream_async
|| g_task_get_source_tag (task) == cdk_pixbuf_save_to_streamv_async
) _g_boolean_var_151 = 1; _g_boolean_var_151; }), 1)) ; else g_warn_message
("CdkPixbuf", "../cdk-pixbuf/cdk-pixbuf-io.c", 3328, ((const
char*) (__func__)), "g_task_get_source_tag (task) == cdk_pixbuf_save_to_stream_async || g_task_get_source_tag (task) == cdk_pixbuf_save_to_streamv_async"
); } while (0)
3328 g_task_get_source_tag (task) == cdk_pixbuf_save_to_streamv_async)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_151
= 0; if (g_task_get_source_tag (task) == cdk_pixbuf_save_to_stream_async
|| g_task_get_source_tag (task) == cdk_pixbuf_save_to_streamv_async
) _g_boolean_var_151 = 1; _g_boolean_var_151; }), 1)) ; else g_warn_message
("CdkPixbuf", "../cdk-pixbuf/cdk-pixbuf-io.c", 3328, ((const
char*) (__func__)), "g_task_get_source_tag (task) == cdk_pixbuf_save_to_stream_async || g_task_get_source_tag (task) == cdk_pixbuf_save_to_streamv_async"
); } while (0)
;
3329
3330 return g_task_propagate_boolean (task, error);
3331}
3332
3333/**
3334 * cdk_pixbuf_format_get_name:
3335 * @format: a `CdkPixbufFormat`
3336 *
3337 * Returns the name of the format.
3338 *
3339 * Returns: (transfer full) (nullable): the name of the format.
3340 *
3341 * Since: 2.2
3342 */
3343gchar *
3344cdk_pixbuf_format_get_name (CdkPixbufFormat *format)
3345{
3346 g_return_val_if_fail (format != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_152
= 0; if (format != ((void*)0)) _g_boolean_var_152 = 1; _g_boolean_var_152
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "format != NULL"); return (((void*
)0)); } } while (0)
;
3347
3348 return g_strdup (format->name)g_strdup_inline (format->name);
3349}
3350
3351/**
3352 * cdk_pixbuf_format_get_description:
3353 * @format: a `CdkPixbufFormat`
3354 *
3355 * Returns a description of the format.
3356 *
3357 * Returns: (transfer full) (nullable): a description of the format.
3358 *
3359 * Since: 2.2
3360 */
3361gchar *
3362cdk_pixbuf_format_get_description (CdkPixbufFormat *format)
3363{
3364 gchar *domain;
3365 const gchar *description;
3366 g_return_val_if_fail (format != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_153
= 0; if (format != ((void*)0)) _g_boolean_var_153 = 1; _g_boolean_var_153
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "format != NULL"); return (((void*
)0)); } } while (0)
;
3367
3368 if (format->domain != NULL((void*)0))
3369 domain = format->domain;
3370 else
3371 domain = GETTEXT_PACKAGE"cdk-pixbuf";
3372 description = g_dgettext (domain, format->description);
3373
3374 return g_strdup (description)g_strdup_inline (description);
3375}
3376
3377/**
3378 * cdk_pixbuf_format_get_mime_types:
3379 * @format: a `CdkPixbufFormat`
3380 *
3381 * Returns the mime types supported by the format.
3382 *
3383 * Returns: (transfer full) (array zero-terminated=1) (nullable): an array of mime types
3384 *
3385 * Since: 2.2
3386 */
3387gchar **
3388cdk_pixbuf_format_get_mime_types (CdkPixbufFormat *format)
3389{
3390 g_return_val_if_fail (format != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_154
= 0; if (format != ((void*)0)) _g_boolean_var_154 = 1; _g_boolean_var_154
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "format != NULL"); return (((void*
)0)); } } while (0)
;
3391
3392 return g_strdupv (format->mime_types);
3393}
3394
3395/**
3396 * cdk_pixbuf_format_get_extensions:
3397 * @format: a `CdkPixbufFormat`
3398 *
3399 * Returns the filename extensions typically used for files in the
3400 * given format.
3401 *
3402 * Returns: (transfer full) (array zero-terminated=1) (nullable): an array of
3403 * filename extensions
3404 *
3405 * Since: 2.2
3406 */
3407gchar **
3408cdk_pixbuf_format_get_extensions (CdkPixbufFormat *format)
3409{
3410 g_return_val_if_fail (format != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_155
= 0; if (format != ((void*)0)) _g_boolean_var_155 = 1; _g_boolean_var_155
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "format != NULL"); return (((void*
)0)); } } while (0)
;
3411
3412 return g_strdupv (format->extensions);
3413}
3414
3415/**
3416 * cdk_pixbuf_format_is_writable:
3417 * @format: a `CdkPixbufFormat`
3418 *
3419 * Returns whether pixbufs can be saved in the given format.
3420 *
3421 * Returns: whether pixbufs can be saved in the given format.
3422 *
3423 * Since: 2.2
3424 */
3425gboolean
3426cdk_pixbuf_format_is_writable (CdkPixbufFormat *format)
3427{
3428 g_return_val_if_fail (format != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_156
= 0; if (format != ((void*)0)) _g_boolean_var_156 = 1; _g_boolean_var_156
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "format != NULL"); return ((0)); }
} while (0)
;
3429
3430 return (format->flags & CDK_PIXBUF_FORMAT_WRITABLE) != 0;
3431}
3432
3433/**
3434 * cdk_pixbuf_format_is_scalable:
3435 * @format: a `CdkPixbufFormat`
3436 *
3437 * Returns whether this image format is scalable.
3438 *
3439 * If a file is in a scalable format, it is preferable to load it at
3440 * the desired size, rather than loading it at the default size and
3441 * scaling the resulting pixbuf to the desired size.
3442 *
3443 * Returns: whether this image format is scalable.
3444 *
3445 * Since: 2.6
3446 */
3447gboolean
3448cdk_pixbuf_format_is_scalable (CdkPixbufFormat *format)
3449{
3450 g_return_val_if_fail (format != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_157
= 0; if (format != ((void*)0)) _g_boolean_var_157 = 1; _g_boolean_var_157
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "format != NULL"); return ((0)); }
} while (0)
;
3451
3452 return (format->flags & CDK_PIXBUF_FORMAT_SCALABLE) != 0;
3453}
3454
3455/**
3456 * cdk_pixbuf_format_is_disabled:
3457 * @format: a `CdkPixbufFormat`
3458 *
3459 * Returns whether this image format is disabled.
3460 *
3461 * See cdk_pixbuf_format_set_disabled().
3462 *
3463 * Returns: whether this image format is disabled.
3464 *
3465 * Since: 2.6
3466 */
3467gboolean
3468cdk_pixbuf_format_is_disabled (CdkPixbufFormat *format)
3469{
3470 g_return_val_if_fail (format != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_158
= 0; if (format != ((void*)0)) _g_boolean_var_158 = 1; _g_boolean_var_158
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "format != NULL"); return ((0)); }
} while (0)
;
3471
3472 return format->disabled;
3473}
3474
3475/**
3476 * cdk_pixbuf_format_set_disabled:
3477 * @format: a `CdkPixbufFormat`
3478 * @disabled: `TRUE` to disable the format @format
3479 *
3480 * Disables or enables an image format.
3481 *
3482 * If a format is disabled, CdkPixbuf won't use the image loader for
3483 * this format to load images.
3484 *
3485 * Applications can use this to avoid using image loaders with an
3486 * inappropriate license, see cdk_pixbuf_format_get_license().
3487 *
3488 * Since: 2.6
3489 */
3490void
3491cdk_pixbuf_format_set_disabled (CdkPixbufFormat *format,
3492 gboolean disabled)
3493{
3494 g_return_if_fail (format != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_159
= 0; if (format != ((void*)0)) _g_boolean_var_159 = 1; _g_boolean_var_159
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "format != NULL"); return; } } while
(0)
;
3495
3496 format->disabled = disabled != FALSE(0);
3497}
3498
3499/**
3500 * cdk_pixbuf_format_get_license:
3501 * @format: a pixbuf format
3502 *
3503 * Returns information about the license of the image loader for the format.
3504 *
3505 * The returned string should be a shorthand for a well known license, e.g.
3506 * "LGPL", "GPL", "QPL", "GPL/QPL", or "other" to indicate some other license.
3507 *
3508 * Returns: (transfer full) (nullable): a string describing the license of the pixbuf format
3509 *
3510 * Since: 2.6
3511 */
3512gchar*
3513cdk_pixbuf_format_get_license (CdkPixbufFormat *format)
3514{
3515 g_return_val_if_fail (format != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_160
= 0; if (format != ((void*)0)) _g_boolean_var_160 = 1; _g_boolean_var_160
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "format != NULL"); return (((void*
)0)); } } while (0)
;
3516
3517 return g_strdup (format->license)g_strdup_inline (format->license);
3518}
3519
3520CdkPixbufFormat *
3521_cdk_pixbuf_get_format (CdkPixbufModule *module)
3522{
3523 g_return_val_if_fail (module != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_161
= 0; if (module != ((void*)0)) _g_boolean_var_161 = 1; _g_boolean_var_161
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "module != NULL"); return (((void*
)0)); } } while (0)
;
3524
3525 return module->info;
3526}
3527
3528/**
3529 * cdk_pixbuf_get_formats:
3530 *
3531 * Obtains the available information about the image formats supported
3532 * by CdkPixbuf.
3533 *
3534 * Returns: (transfer container) (element-type CdkPixbufFormat): A list of
3535 * support image formats.
3536 *
3537 * Since: 2.2
3538 */
3539GSList *
3540cdk_pixbuf_get_formats (void)
3541{
3542 GSList *result = NULL((void*)0);
3543 GSList *modules;
3544
3545 for (modules = get_file_formats (); modules; modules = g_slist_next (modules)((modules) ? (((GSList *)(modules))->next) : ((void*)0))) {
3546 CdkPixbufModule *module = (CdkPixbufModule *)modules->data;
3547 CdkPixbufFormat *info = _cdk_pixbuf_get_format (module);
3548 result = g_slist_prepend (result, info);
3549 }
3550
3551 return result;
3552}
3553
3554/**
3555 * cdk_pixbuf_format_copy:
3556 * @format: a pixbuf format
3557 *
3558 * Creates a copy of `format`.
3559 *
3560 * Returns: (transfer full) (nullable): the newly allocated copy of a `CdkPixbufFormat`. Use
3561 * cdk_pixbuf_format_free() to free the resources when done
3562 *
3563 * Since: 2.22
3564 */
3565CdkPixbufFormat *
3566cdk_pixbuf_format_copy (const CdkPixbufFormat *format)
3567{
3568 if (G_LIKELY (format != NULL)(__builtin_expect (__extension__ ({ int _g_boolean_var_162 = 0
; if (format != ((void*)0)) _g_boolean_var_162 = 1; _g_boolean_var_162
; }), 1))
)
3569 return g_slice_dup (CdkPixbufFormat, format)(1 ? (CdkPixbufFormat*) g_slice_copy ((sizeof (CdkPixbufFormat
) > 0 ? sizeof (CdkPixbufFormat) : 1), (format)) : ((void)
((CdkPixbufFormat*) 0 == (format)), (CdkPixbufFormat*) 0))
;
3570
3571 return NULL((void*)0);
3572}
3573
3574/**
3575 * cdk_pixbuf_format_free:
3576 * @format: a pixbuf format
3577 *
3578 * Frees the resources allocated when copying a `CdkPixbufFormat`
3579 * using cdk_pixbuf_format_copy()
3580 *
3581 * Since: 2.22
3582 */
3583void
3584cdk_pixbuf_format_free (CdkPixbufFormat *format)
3585{
3586 if (G_LIKELY (format != NULL)(__builtin_expect (__extension__ ({ int _g_boolean_var_163 = 0
; if (format != ((void*)0)) _g_boolean_var_163 = 1; _g_boolean_var_163
; }), 1))
)
3587 g_slice_free (CdkPixbufFormat, format)do { if (1) g_slice_free1 (sizeof (CdkPixbufFormat), (format)
); else (void) ((CdkPixbufFormat*) 0 == (format)); } while (0
)
;
3588}
3589
3590/**
3591 * cdk_pixbuf_format_is_save_option_supported:
3592 * @format: a pixbuf format
3593 * @option_key: the name of an option
3594 *
3595 * Returns `TRUE` if the save option specified by @option_key is supported when
3596 * saving a pixbuf using the module implementing @format.
3597 *
3598 * See cdk_pixbuf_save() for more information about option keys.
3599 *
3600 * Returns: `TRUE` if the specified option is supported
3601 *
3602 * Since: 2.36
3603 */
3604gboolean
3605cdk_pixbuf_format_is_save_option_supported (CdkPixbufFormat *format,
3606 const gchar *option_key)
3607{
3608 CdkPixbufModule *module;
3609
3610 g_return_val_if_fail (format != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_164
= 0; if (format != ((void*)0)) _g_boolean_var_164 = 1; _g_boolean_var_164
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "format != NULL"); return ((0)); }
} while (0)
;
1
Assuming 'format' is not equal to null
2
Taking true branch
3
Taking true branch
4
Loop condition is false. Exiting loop
3611 g_return_val_if_fail (option_key != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_165
= 0; if (option_key != ((void*)0)) _g_boolean_var_165 = 1; _g_boolean_var_165
; }), 1))) { } else { g_return_if_fail_warning ("CdkPixbuf", (
(const char*) (__func__)), "option_key != NULL"); return ((0)
); } } while (0)
;
5
Assuming 'option_key' is not equal to null
6
Taking true branch
7
Taking true branch
8
Loop condition is false. Exiting loop
3612
3613 module = _cdk_pixbuf_get_named_module (format->name, NULL((void*)0));
9
Calling '_cdk_pixbuf_get_named_module'
3614 if (!module)
3615 return FALSE(0);
3616
3617 if (!_cdk_pixbuf_load_module (module, NULL((void*)0)))
3618 return FALSE(0);
3619
3620 if (!module->is_save_option_supported)
3621 return FALSE(0);
3622
3623 return (* module->is_save_option_supported) (option_key);
3624}
3625
3626G_DEFINE_BOXED_TYPE (CdkPixbufFormat, cdk_pixbuf_format,static GType cdk_pixbuf_format_get_type_once (void); GType cdk_pixbuf_format_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= cdk_pixbuf_format_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType cdk_pixbuf_format_get_type_once (
void) { GType (* _g_register_boxed) (const gchar *, union { CdkPixbufFormat
* (*do_copy_type) (CdkPixbufFormat *); CdkPixbufFormat * (*do_const_copy_type
) (const CdkPixbufFormat *); GBoxedCopyFunc do_copy_boxed; } __attribute__
((__transparent_union__)), union { void (* do_free_type) (CdkPixbufFormat
*); GBoxedFreeFunc do_free_boxed; } __attribute__((__transparent_union__
)) ) = g_boxed_type_register_static; GType g_define_type_id =
_g_register_boxed (g_intern_static_string ("CdkPixbufFormat"
), cdk_pixbuf_format_copy, cdk_pixbuf_format_free); { {{};} }
return g_define_type_id; }
3627 cdk_pixbuf_format_copy,static GType cdk_pixbuf_format_get_type_once (void); GType cdk_pixbuf_format_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= cdk_pixbuf_format_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType cdk_pixbuf_format_get_type_once (
void) { GType (* _g_register_boxed) (const gchar *, union { CdkPixbufFormat
* (*do_copy_type) (CdkPixbufFormat *); CdkPixbufFormat * (*do_const_copy_type
) (const CdkPixbufFormat *); GBoxedCopyFunc do_copy_boxed; } __attribute__
((__transparent_union__)), union { void (* do_free_type) (CdkPixbufFormat
*); GBoxedFreeFunc do_free_boxed; } __attribute__((__transparent_union__
)) ) = g_boxed_type_register_static; GType g_define_type_id =
_g_register_boxed (g_intern_static_string ("CdkPixbufFormat"
), cdk_pixbuf_format_copy, cdk_pixbuf_format_free); { {{};} }
return g_define_type_id; }
3628 cdk_pixbuf_format_free)static GType cdk_pixbuf_format_get_type_once (void); GType cdk_pixbuf_format_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= cdk_pixbuf_format_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType cdk_pixbuf_format_get_type_once (
void) { GType (* _g_register_boxed) (const gchar *, union { CdkPixbufFormat
* (*do_copy_type) (CdkPixbufFormat *); CdkPixbufFormat * (*do_const_copy_type
) (const CdkPixbufFormat *); GBoxedCopyFunc do_copy_boxed; } __attribute__
((__transparent_union__)), union { void (* do_free_type) (CdkPixbufFormat
*); GBoxedFreeFunc do_free_boxed; } __attribute__((__transparent_union__
)) ) = g_boxed_type_register_static; GType g_define_type_id =
_g_register_boxed (g_intern_static_string ("CdkPixbufFormat"
), cdk_pixbuf_format_copy, cdk_pixbuf_format_free); { {{};} }
return g_define_type_id; }