diff --git a/plug-ins/common/file-csource.c b/plug-ins/common/file-csource.c index 4d87def234..86f04ec905 100644 --- a/plug-ins/common/file-csource.c +++ b/plug-ins/common/file-csource.c @@ -38,7 +38,6 @@ typedef struct { - gchar *file_name; gchar *prefixed_name; gchar *comment; gboolean use_comment; @@ -58,7 +57,8 @@ static void run (const gchar *name, gint *nreturn_vals, GimpParam **return_vals); -static gboolean save_image (Config *config, +static gboolean save_image (GFile *file, + Config *config, gint32 image_ID, gint32 drawable_ID, GError **error); @@ -75,7 +75,6 @@ const GimpPlugInInfo PLUG_IN_INFO = static Config config = { - NULL, /* file_name */ "gimp_image", /* prefixed_name */ NULL, /* comment */ FALSE, /* use_comment */ @@ -116,6 +115,7 @@ query (void) save_args, NULL); gimp_register_file_handler_mime (SAVE_PROC, "text/x-csrc"); + gimp_register_file_handler_uri (SAVE_PROC); gimp_register_save_handler (SAVE_PROC, "c", ""); } @@ -150,16 +150,12 @@ run (const gchar *name, gint32 drawable_ID = param[2].data.d_int32; GimpParasite *parasite; gchar *x; - GimpImageType drawable_type = gimp_drawable_type (drawable_ID); gimp_get_data (SAVE_PROC, &config); + config.prefixed_name = "gimp_image"; config.comment = NULL; - - config.file_name = param[3].data.d_string; - config.alpha = (drawable_type == GIMP_RGBA_IMAGE || - drawable_type == GIMP_GRAYA_IMAGE || - drawable_type == GIMP_INDEXEDA_IMAGE); + config.alpha = gimp_drawable_has_alpha (drawable_ID); parasite = gimp_image_get_parasite (image_ID, "gimp-comment"); if (parasite) @@ -202,7 +198,8 @@ run (const gchar *name, } } - if (! save_image (&config, image_ID, drawable_ID, &error)) + if (! save_image (g_file_new_for_uri (param[3].data.d_string), + &config, image_ID, drawable_ID, &error)) { status = GIMP_PDB_EXECUTION_ERROR; @@ -297,101 +294,145 @@ rl_encode_rgbx (guint8 *bp, return bp; } -static inline void -save_rle_decoder (FILE *fp, - const gchar *macro_name, - const gchar *s_uint, - const gchar *s_uint_8, - guint n_ch) +static gboolean print (GOutputStream *stream, + GError **error, + const gchar *format, + ...) G_GNUC_PRINTF (3, 4); + +static gboolean +print (GOutputStream *stream, + GError **error, + const gchar *format, + ...) { - fprintf (fp, "#define %s_RUN_LENGTH_DECODE(image_buf, rle_data, size, bpp) do \\\n", - macro_name); - fprintf (fp, "{ %s __bpp; %s *__ip; const %s *__il, *__rd; \\\n", s_uint, s_uint_8, s_uint_8); - fprintf (fp, " __bpp = (bpp); __ip = (image_buf); __il = __ip + (size) * __bpp; \\\n"); + va_list args; + gboolean success; - fprintf (fp, " __rd = (rle_data); if (__bpp > 3) { /* RGBA */ \\\n"); + va_start (args, format); + success = gimp_output_stream_vprintf (stream, NULL, NULL, + error, format, args); + va_end (args); - fprintf (fp, " while (__ip < __il) { %s __l = *(__rd++); \\\n", s_uint); - fprintf (fp, " if (__l & 128) { __l = __l - 128; \\\n"); - fprintf (fp, " do { memcpy (__ip, __rd, 4); __ip += 4; } while (--__l); __rd += 4; \\\n"); - fprintf (fp, " } else { __l *= 4; memcpy (__ip, __rd, __l); \\\n"); - fprintf (fp, " __ip += __l; __rd += __l; } } \\\n"); - - fprintf (fp, " } else { /* RGB */ \\\n"); - - fprintf (fp, " while (__ip < __il) { %s __l = *(__rd++); \\\n", s_uint); - fprintf (fp, " if (__l & 128) { __l = __l - 128; \\\n"); - fprintf (fp, " do { memcpy (__ip, __rd, 3); __ip += 3; } while (--__l); __rd += 3; \\\n"); - fprintf (fp, " } else { __l *= 3; memcpy (__ip, __rd, __l); \\\n"); - fprintf (fp, " __ip += __l; __rd += __l; } } \\\n"); - - fprintf (fp, " } } while (0)\n"); + return success; } -static inline guint -save_uchar (FILE *fp, - guint c, - guint8 d, - Config *config) +static inline gboolean +save_rle_decoder (GOutputStream *output, + const gchar *macro_name, + const gchar *s_uint, + const gchar *s_uint_8, + guint n_ch, + GError **error) +{ + return + print (output, error, + "#define %s_RUN_LENGTH_DECODE(image_buf, rle_data, size, bpp) do \\\n", + macro_name) && + print (output, error, + "{ %s __bpp; %s *__ip; const %s *__il, *__rd; \\\n", + s_uint, s_uint_8, s_uint_8) && + print (output, error, + " __bpp = (bpp); __ip = (image_buf); __il = __ip + (size) * __bpp; \\\n" + " __rd = (rle_data); if (__bpp > 3) { /* RGBA */ \\\n" + " while (__ip < __il) { %s __l = *(__rd++); \\\n", + s_uint) && + print (output, error, + " if (__l & 128) { __l = __l - 128; \\\n" + " do { memcpy (__ip, __rd, 4); __ip += 4; } while (--__l); __rd += 4; \\\n" + " } else { __l *= 4; memcpy (__ip, __rd, __l); \\\n" + " __ip += __l; __rd += __l; } } \\\n" + " } else { /* RGB */ \\\n" + " while (__ip < __il) { %s __l = *(__rd++); \\\n", + s_uint) && + print (output, error, + " if (__l & 128) { __l = __l - 128; \\\n" + " do { memcpy (__ip, __rd, 3); __ip += 3; } while (--__l); __rd += 3; \\\n" + " } else { __l *= 3; memcpy (__ip, __rd, __l); \\\n" + " __ip += __l; __rd += __l; } } \\\n" + " } } while (0)\n"); +} + +static inline gboolean +save_uchar (GOutputStream *output, + guint *c, + guint8 d, + Config *config, + GError **error) { static guint8 pad = 0; - if (c > 74) + if (*c > 74) { - if (!config->use_macros) + if (! config->use_macros) { - fprintf (fp, "\"\n \""); - c = 3; + if (! print (output, error, "\"\n \"")) + return FALSE; + + *c = 3; } else { - fprintf (fp, "\"\n \""); - c = 2; + if (! print (output, error, "\"\n \"")) + return FALSE; + + *c = 2; } } + if (d < 33 || d > 126) { - fprintf (fp, "\\%o", d); - c += 1 + 1 + (d > 7) + (d > 63); + if (! print (output, error, "\\%o", d)) + return FALSE; + + *c += 1 + 1 + (d > 7) + (d > 63); pad = d < 64; - return c; + return TRUE; } if (d == '\\') { - fputs ("\\\\", fp); - c += 2; + if (! print (output, error, "\\\\")) + return FALSE; + + *c += 2; } else if (d == '"') { - fputs ("\\\"", fp); - c += 2; + if (! print (output, error, "\\\"")) + return FALSE; + + *c += 2; } else if (pad && d >= '0' && d <= '9') { - fputs ("\"\"", fp); - fputc (d, fp); - c += 3; + if (! print (output, error, "\"\"%c", d)) + return FALSE; + + *c += 3; } else { - fputc (d, fp); - c += 1; + if (! print (output, error, "%c", d)) + return FALSE; + + *c += 1; } + pad = 0; - return c; + return TRUE; } static gboolean -save_image (Config *config, +save_image (GFile *file, + Config *config, gint32 image_ID, gint32 drawable_ID, GError **error) { + GOutputStream *output; GeglBuffer *buffer; - FILE *fp; GimpImageType drawable_type = gimp_drawable_type (drawable_ID); gchar *s_uint_8, *s_uint, *s_char, *s_null; guint c; @@ -404,13 +445,18 @@ save_image (Config *config, gint x, y, pad, n_bytes, bpp; gint drawable_bpp; - fp = g_fopen (config->file_name, "w"); - if (! fp) + output = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, 0, NULL, error)); + if (output) + { + GOutputStream *buffered; + + buffered = g_buffered_output_stream_new (output); + g_object_unref (output); + + output = buffered; + } + else { - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), - _("Could not open '%s' for writing: %s"), - gimp_filename_to_utf8 (config->file_name), - g_strerror (errno)); return FALSE; } @@ -529,150 +575,261 @@ save_image (Config *config, macro_name = g_ascii_strup (config->prefixed_name, -1); - basename = g_path_get_basename (config->file_name); + basename = g_file_get_basename (file); - fprintf (fp, "/* GIMP %s C-Source image dump %s(%s) */\n\n", - config->alpha ? "RGBA" : "RGB", - config->use_rle ? "1-byte-run-length-encoded " : "", - basename); + if (! print (output, error, + "/* GIMP %s C-Source image dump %s(%s) */\n\n", + config->alpha ? "RGBA" : "RGB", + config->use_rle ? "1-byte-run-length-encoded " : "", + basename)) + goto fail; g_free (basename); if (config->use_rle && !config->use_macros) - save_rle_decoder (fp, - macro_name, - config->glib_types ? "guint" : "unsigned int", - config->glib_types ? "guint8" : "unsigned char", - config->alpha ? 4 : 3); + { + if (! save_rle_decoder (output, + macro_name, + config->glib_types ? "guint" : "unsigned int", + config->glib_types ? "guint8" : "unsigned char", + config->alpha ? 4 : 3, + error)) + goto fail; + } if (!config->use_macros) { - fprintf (fp, "static const struct {\n"); - fprintf (fp, " %s\t width;\n", s_uint); - fprintf (fp, " %s\t height;\n", s_uint); - fprintf (fp, " %s\t bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ \n", - s_uint); + if (! print (output, error, + "static const struct {\n" + " %s\t width;\n" + " %s\t height;\n" + " %s\t bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ \n", + s_uint, s_uint, s_uint)) + goto fail; + if (config->use_comment) - fprintf (fp, " %s\t*comment;\n", s_char); - fprintf (fp, " %s\t %spixel_data[", - s_uint_8, - config->use_rle ? "rle_" : ""); + { + if (! print (output, error, " %s\t*comment;\n", s_char)) + goto fail; + } + + if (! print (output, error, + " %s\t %spixel_data[", + s_uint_8, + config->use_rle ? "rle_" : "")) + goto fail; + if (config->use_rle) - fprintf (fp, "%u + 1];\n", (guint) (img_buffer_end - img_buffer)); + { + if (! print (output, error, + "%u + 1];\n", + (guint) (img_buffer_end - img_buffer))) + goto fail; + } else - fprintf (fp, "%u * %u * %u + 1];\n", - width, - height, - config->rgb565 ? 2 : (config->alpha ? 4 : 3)); - fprintf (fp, "} %s = {\n", config->prefixed_name); - fprintf (fp, " %u, %u, %u,\n", - width, - height, - config->rgb565 ? 2 : (config->alpha ? 4 : 3)); + { + if (! print (output, error, + "%u * %u * %u + 1];\n", + width, + height, + config->rgb565 ? 2 : (config->alpha ? 4 : 3))) + goto fail; + } + + if (! print (output, error, "} %s = {\n", config->prefixed_name)) + goto fail; + + if (! print (output, error, + " %u, %u, %u,\n", + width, + height, + config->rgb565 ? 2 : (config->alpha ? 4 : 3))) + goto fail; } else /* use macros */ { - fprintf (fp, "#define %s_WIDTH (%u)\n", - macro_name, width); - fprintf (fp, "#define %s_HEIGHT (%u)\n", - macro_name, height); - fprintf (fp, "#define %s_BYTES_PER_PIXEL (%u) /* 3:RGB, 4:RGBA */\n", - macro_name, config->alpha ? 4 : 3); + if (! print (output, error, + "#define %s_WIDTH (%u)\n" + "#define %s_HEIGHT (%u)\n" + "#define %s_BYTES_PER_PIXEL (%u) /* 3:RGB, 4:RGBA */\n", + macro_name, width, + macro_name, height, + macro_name, config->alpha ? 4 : 3)) + { + goto fail; + } } + if (config->use_comment && !config->comment) { - if (!config->use_macros) - fprintf (fp, " %s,\n", s_null); - else /* use macros */ - fprintf (fp, "#define %s_COMMENT (%s)\n", macro_name, s_null); + if (! config->use_macros) + { + if (! print (output, error, " %s,\n", s_null)) + goto fail; + } + else + { + if (! print (output, error, + "#define %s_COMMENT (%s)\n", + macro_name, s_null)) + goto fail; + } } else if (config->use_comment) { gchar *p = config->comment - 1; if (config->use_macros) - fprintf (fp, "#define %s_COMMENT \\\n", macro_name); - fprintf (fp, " \""); + { + if (! print (output, error, "#define %s_COMMENT \\\n", macro_name)) + goto fail; + } + + if (! print (output, error, " \"")) + goto fail; + while (*(++p)) - if (*p == '\\') - fprintf (fp, "\\\\"); - else if (*p == '"') - fprintf (fp, "\\\""); - else if (*p == '\n' && p[1]) - fprintf (fp, "\\n\"%s\n \"", - config->use_macros ? " \\" : ""); - else if (*p == '\n') - fprintf (fp, "\\n"); - else if (*p == '\r') - fprintf (fp, "\\r"); - else if (*p == '\b') - fprintf (fp, "\\b"); - else if (*p == '\f') - fprintf (fp, "\\f"); - else if (*p >= 32 && *p <= 126) - fprintf (fp, "%c", *p); - else - fprintf (fp, "\\%03o", *p); - if (!config->use_macros) - fprintf (fp, "\",\n"); - else /* use macros */ - fprintf (fp, "\"\n"); + { + gboolean success = FALSE; + + if (*p == '\\') + success = print (output, error, "\\\\"); + else if (*p == '"') + success = print (output, error, "\\\""); + else if (*p == '\n' && p[1]) + success = print (output, error, + "\\n\"%s\n \"", + config->use_macros ? " \\" : ""); + else if (*p == '\n') + success = print (output, error, "\\n"); + else if (*p == '\r') + success = print (output, error, "\\r"); + else if (*p == '\b') + success = print (output, error, "\\b"); + else if (*p == '\f') + success = print (output, error, "\\f"); + else if (*p >= 32 && *p <= 126) + success = print (output, error, "%c", *p); + else + success = print (output, error, "\\%03o", *p); + + if (! success) + goto fail; + } + + if (! config->use_macros) + { + if (! print (output, error, "\",\n")) + goto fail; + } + else + { + if (! print (output, error, "\"\n")) + goto fail; + } } + if (config->use_macros) { - fprintf (fp, "#define %s_%sPIXEL_DATA ((%s*) %s_%spixel_data)\n", - macro_name, - config->use_rle ? "RLE_" : "", - s_uint_8, - macro_name, - config->use_rle ? "rle_" : ""); + if (! print (output, error, + "#define %s_%sPIXEL_DATA ((%s*) %s_%spixel_data)\n", + macro_name, + config->use_rle ? "RLE_" : "", + s_uint_8, + macro_name, + config->use_rle ? "rle_" : "")) + goto fail; + if (config->use_rle) - save_rle_decoder (fp, - macro_name, - s_uint, - s_uint_8, - config->alpha ? 4 : 3); - fprintf (fp, "static const %s %s_%spixel_data[", - s_uint_8, - macro_name, - config->use_rle ? "rle_" : ""); + { + if (! save_rle_decoder (output, + macro_name, + s_uint, + s_uint_8, + config->alpha ? 4 : 3, + error)) + goto fail; + } + + if (! print (output, error, + "static const %s %s_%spixel_data[", + s_uint_8, + macro_name, + config->use_rle ? "rle_" : "")) + goto fail; + if (config->use_rle) - fprintf (fp, "%u] =\n", (guint) (img_buffer_end - img_buffer)); + { + if (! print (output, error, + "%u] =\n", + (guint) (img_buffer_end - img_buffer))) + goto fail; + } else - fprintf (fp, "%u * %u * %u + 1] =\n", - width, - height, - config->alpha ? 4 : 3); - fprintf (fp, "(\""); + { + if (! print (output, error, + "%u * %u * %u + 1] =\n", + width, + height, + config->alpha ? 4 : 3)) + goto fail; + } + + if (! print (output, error, "(\"")) + goto fail; + c = 2; } else { - fprintf (fp, " \""); + if (! print (output, error, " \"")) + goto fail; + c = 3; } + switch (drawable_type) { case GIMP_RGB_IMAGE: case GIMP_RGBA_IMAGE: do - c = save_uchar (fp, c, *(img_buffer++), config); + { + if (! save_uchar (output, &c, *(img_buffer++), config, error)) + goto fail; + } while (img_buffer < img_buffer_end); break; + default: g_warning ("unhandled drawable type (%d)", drawable_type); - fclose (fp); - return FALSE; + goto fail; } - if (!config->use_macros) - fprintf (fp, "\",\n};\n\n"); - else /* use macros */ - fprintf (fp, "\");\n\n"); - fclose (fp); + if (! config->use_macros) + { + if (! print (output, error, "\",\n};\n\n")) + goto fail; + } + else + { + if (! print (output, error, "\");\n\n")) + goto fail; + } + + if (! g_output_stream_close (output, NULL, error)) + goto fail; + + g_object_unref (output); g_object_unref (buffer); return TRUE; + + fail: + + g_object_unref (output); + g_object_unref (buffer); + + return FALSE; } static void