Bug Summary

File:_build/../cdk-pixbuf/cdk-pixbuf-io.c
Warning:line 2442, column 21
Value of 'errno' was not checked and may be overwritten by function 'fread'

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.4501.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-08-29-084133-8035-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) ||
180 !file_formats_inited)
181 file_formats_inited = 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)(__builtin_object_size ((bin_dir), 0) != ((size_t) - 1)) ? g_free_sized
(bin_dir, __builtin_object_size ((bin_dir), 0)) : (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)(__builtin_object_size ((exe_path), 0) != ((size_t) - 1)) ? g_free_sized
(exe_path, __builtin_object_size ((exe_path), 0)) : (g_free)
(exe_path)
;
234 g_free (bin_dir)(__builtin_object_size ((bin_dir), 0) != ((size_t) - 1)) ? g_free_sized
(bin_dir, __builtin_object_size ((bin_dir), 0)) : (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)(__builtin_object_size ((tmp), 0) != ((size_t) - 1)) ? g_free_sized
(tmp, __builtin_object_size ((tmp), 0)) : (g_free) (tmp)
;
273 g_free (tmp2)(__builtin_object_size ((tmp2), 0) != ((size_t) - 1)) ? g_free_sized
(tmp2, __builtin_object_size ((tmp2), 0)) : (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) {
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)(__builtin_object_size ((filename_utf8), 0) != ((size_t) - 1)
) ? g_free_sized (filename_utf8, __builtin_object_size ((filename_utf8
), 0)) : (g_free) (filename_utf8)
;
410 return FALSE(0);
411 }
412
413 num_formats = g_slist_length (file_formats);
414
415 while (!have_error && g_io_channel_read_line (channel, &line_buf, NULL((void*)0), &term, NULL((void*)0)) == G_IO_STATUS_NORMAL) {
416 const char *p;
417
418 p = line_buf;
419
420 line_buf[term] = 0;
421
422 if (!skip_space (&p)) {
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 == '#')
433 goto next_line;
434
435 if (!module) {
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; }))
;
438 n_patterns = 0;
439
440 if (!scan_string (&p, tmp_buf)) {
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)(__builtin_object_size ((pattern->prefix), 0) != ((size_t)
- 1)) ? g_free_sized (pattern->prefix, __builtin_object_size
((pattern->prefix), 0)) : (g_free) (pattern->prefix)
;
537 g_free (pattern->mask)(__builtin_object_size ((pattern->mask), 0) != ((size_t) -
1)) ? g_free_sized (pattern->mask, __builtin_object_size (
(pattern->mask), 0)) : (g_free) (pattern->mask)
;
538 g_free (pattern)(__builtin_object_size ((pattern), 0) != ((size_t) - 1)) ? g_free_sized
(pattern, __builtin_object_size ((pattern), 0)) : (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)(__builtin_object_size ((line_buf), 0) != ((size_t) - 1)) ? g_free_sized
(line_buf, __builtin_object_size ((line_buf), 0)) : (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)))))
;
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)(__builtin_object_size ((filename_utf8), 0) != ((size_t) - 1)
) ? g_free_sized (filename_utf8, __builtin_object_size ((filename_utf8
), 0)) : (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)(__builtin_object_size ((filename), 0) != ((size_t) - 1)) ? g_free_sized
(filename, __builtin_object_size ((filename), 0)) : (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)(__builtin_object_size ((__builtin_module), 0) != ((size_t) -
1)) ? g_free_sized (__builtin_module, __builtin_object_size (
(__builtin_module), 0)) : (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));
707 g_free (module_file)(__builtin_object_size ((module_file), 0) != ((size_t) - 1)) ?
g_free_sized (module_file, __builtin_object_size ((module_file
), 0)) : (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)(__builtin_object_size ((path_utf8), 0) != ((size_t) - 1)) ? g_free_sized
(path_utf8, __builtin_object_size ((path_utf8), 0)) : (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)(__builtin_object_size ((path_utf8), 0) != ((size_t) - 1)) ? g_free_sized
(path_utf8, __builtin_object_size ((path_utf8), 0)) : (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))) {
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)(__builtin_object_size ((mime_type), 0) != ((size_t) - 1)) ? g_free_sized
(mime_type, __builtin_object_size ((mime_type), 0)) : (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)(__builtin_object_size ((type), 0) != ((size_t) - 1)) ? g_free_sized
(type, __builtin_object_size ((type), 0)) : (g_free) (type)
;
1012 selected = module;
1013 break;
1014 }
1015 g_free (type)(__builtin_object_size ((type), 0) != ((size_t) - 1)) ? g_free_sized
(type, __builtin_object_size ((type), 0)) : (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)(__builtin_object_size ((mime_type), 0) != ((size_t) - 1)) ? g_free_sized
(mime_type, __builtin_object_size ((mime_type), 0)) : (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)(__builtin_object_size ((display_name), 0) != ((size_t) - 1))
? g_free_sized (display_name, __builtin_object_size ((display_name
), 0)) : (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)(__builtin_object_size ((display_name), 0) != ((size_t) - 1))
? g_free_sized (display_name, __builtin_object_size ((display_name
), 0)) : (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)(__builtin_object_size ((display_name), 0) != ((size_t) - 1))
? g_free_sized (display_name, __builtin_object_size ((display_name
), 0)) : (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)(__builtin_object_size ((display_name), 0) != ((size_t) - 1))
? g_free_sized (display_name, __builtin_object_size ((display_name
), 0)) : (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)(__builtin_object_size ((old), 0) != ((size_t) - 1)) ? g_free_sized
(old, __builtin_object_size ((old), 0)) : (g_free) (old)
;
1275 g_free (display_name)(__builtin_object_size ((display_name), 0) != ((size_t) - 1))
? g_free_sized (display_name, __builtin_object_size ((display_name
), 0)) : (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)(__builtin_object_size ((display_name), 0) != ((size_t) - 1))
? g_free_sized (display_name, __builtin_object_size ((display_name
), 0)) : (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)(__builtin_object_size ((display_name), 0) != ((size_t) - 1))
? g_free_sized (display_name, __builtin_object_size ((display_name
), 0)) : (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)(__builtin_object_size ((data->filename), 0) != ((size_t) -
1)) ? g_free_sized (data->filename, __builtin_object_size
((data->filename), 0)) : (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)) {
40
Assuming 'buf' is not equal to NULL
41
Taking false branch
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)
42
Assuming the condition is false
43
Taking false branch
2425 goto end;
2426 f = fdopen (fd, "wb+");
2427 if (f
43.1
'f' is not equal to NULL
== NULL((void*)0)) {
44
Taking false branch
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)
45
Assuming 'retval' is not equal to 0
46
Taking false branch
2438 goto end;
2439
2440 rewind (f);
47
After calling 'rewind' reading 'errno' is required to find out if the call has failed
2441 for (;;) {
48
Loop condition is true. Entering loop body
2442 n = fread (buf, 1, TMP_FILE_BUF_SIZE4096, f);
49
Value of 'errno' was not checked and may be overwritten by function 'fread'
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)(__builtin_object_size ((filename), 0) != ((size_t) - 1)) ? g_free_sized
(filename, __builtin_object_size ((filename), 0)) : (g_free)
(filename)
;
2467 }
2468 g_free (buf)(__builtin_object_size ((buf), 0) != ((size_t) - 1)) ? g_free_sized
(buf, __builtin_object_size ((buf), 0)) : (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))
32
Assuming 'image_module' is not equal to NULL
33
Taking false branch
2488 return FALSE(0);
2489
2490 if (!_cdk_pixbuf_load_module (image_module, error))
34
Taking false branch
2491 return FALSE(0);
2492
2493 if (image_module->save_to_callback) {
35
Assuming field 'save_to_callback' is null
36
Taking false branch
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) {
37
Assuming field 'save' is non-null
38
Taking true branch
2499 /* use a temporary file */
2500 ret = save_to_callback_with_tmp_file (image_module, pixbuf,
39
Calling 'save_to_callback_with_tmp_file'
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)(__builtin_object_size ((display_name), 0) != ((size_t) - 1))
? g_free_sized (display_name, __builtin_object_size ((display_name
), 0)) : (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)(__builtin_object_size ((display_name), 0) != ((size_t) - 1))
? g_free_sized (display_name, __builtin_object_size ((display_name
), 0)) : (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)
;
2
Assuming '__inst' is non-null
3
Taking false branch
4
Assuming field 'g_class' is null
5
Assuming the condition is true
6
Taking true branch
7
Taking true branch
8
Loop condition is false. Exiting loop
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)
;
9
Assuming the condition is true
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
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)
;
13
Assuming the condition is true
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
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)
;
17
Assuming the condition is true
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
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)
;
21
Taking true branch
22
Taking true branch
23
Loop condition is false. Exiting loop
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)
;
24
Assuming 'type' is not equal to null
25
Taking true branch
26
Taking true branch
27
Loop condition is false. Exiting loop
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)
;
28
Taking true branch
29
Taking true branch
30
Loop condition is false. Exiting loop
2841
2842 result = cdk_pixbuf_real_save_to_callback (pixbuf,
31
Calling 'cdk_pixbuf_real_save_to_callback'
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)(__builtin_object_size ((sdata.buffer), 0) != ((size_t) - 1))
? g_free_sized (sdata.buffer, __builtin_object_size ((sdata.
buffer), 0)) : (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)(__builtin_object_size ((data->type), 0) != ((size_t) - 1)
) ? g_free_sized (data->type, __builtin_object_size ((data
->type), 0)) : (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,
1
Calling 'cdk_pixbuf_save_to_callbackv'
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)
;
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)
;
3612
3613 module = _cdk_pixbuf_get_named_module (format->name, NULL((void*)0));
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; }