static guchar * wmf_load_file (const gchar *filename, guint *width, guint *height, GError **error) { GMappedFile *file; guchar *pixels = NULL; /* the bits we need to decode the WMF via libwmf2's GD layer */ wmf_error_t err; gulong flags; wmf_gd_t *ddata = NULL; wmfAPI *API = NULL; wmfAPI_Options api_options; wmfD_Rect bbox; gint *gd_pixels = NULL; *width = *height = -1; file = g_mapped_file_new (filename, FALSE, error); if (! file) return NULL; flags = WMF_OPT_IGNORE_NONFATAL | WMF_OPT_FUNCTION; api_options.function = wmf_gd_function; err = wmf_api_create (&API, flags, &api_options); if (err != wmf_E_None) goto _wmf_error; ddata = WMF_GD_GetData (API); ddata->type = wmf_gd_image; err = wmf_mem_open (API, (guchar *) g_mapped_file_get_contents (file), g_mapped_file_get_length (file)); if (err != wmf_E_None) goto _wmf_error; err = wmf_scan (API, 0, &bbox); if (err != wmf_E_None) goto _wmf_error; err = wmf_display_size (API, width, height, load_vals.resolution, load_vals.resolution); if (err != wmf_E_None || *width <= 0 || *height <= 0) goto _wmf_error; if (load_vals.width > 0 && load_vals.height > 0) { *width = load_vals.width; *height = load_vals.height; } ddata->bbox = bbox; ddata->width = *width; ddata->height = *height; err = wmf_play (API, 0, &bbox); if (err != wmf_E_None) goto _wmf_error; if (ddata->gd_image != NULL) gd_pixels = wmf_gd_image_pixels (ddata->gd_image); if (gd_pixels == NULL) goto _wmf_error; pixels = pixbuf_gd_convert (gd_pixels, *width, *height); if (pixels == NULL) goto _wmf_error; _wmf_error: if (API) { wmf_mem_close (API); wmf_api_destroy (API); } g_mapped_file_unref (file); /* FIXME: improve error message */ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Could not open '%s' for reading"), gimp_filename_to_utf8 (filename)); return pixels; }
/* This function retrieves the pixel size from a WMF file. */ static gboolean load_wmf_size (const gchar *filename, WmfLoadVals *vals) { GMappedFile *file; /* the bits we need to decode the WMF via libwmf2's GD layer */ wmf_error_t err; gulong flags; wmf_gd_t *ddata = NULL; wmfAPI *API = NULL; wmfAPI_Options api_options; wmfD_Rect bbox; guint width = -1; guint height = -1; gboolean success = TRUE; file = g_mapped_file_new (filename, FALSE, NULL); if (! file) return FALSE; flags = WMF_OPT_IGNORE_NONFATAL | WMF_OPT_FUNCTION; api_options.function = wmf_gd_function; err = wmf_api_create (&API, flags, &api_options); if (err != wmf_E_None) success = FALSE; ddata = WMF_GD_GetData (API); ddata->type = wmf_gd_image; err = wmf_mem_open (API, (guchar *) g_mapped_file_get_contents (file), g_mapped_file_get_length (file)); if (err != wmf_E_None) success = FALSE; err = wmf_scan (API, 0, &bbox); if (err != wmf_E_None) success = FALSE; err = wmf_display_size (API, &width, &height, vals->resolution, vals->resolution); if (err != wmf_E_None || width <= 0 || height <= 0) success = FALSE; wmf_mem_close (API); g_mapped_file_unref (file); if (width < 1 || height < 1) { width = WMF_DEFAULT_SIZE; height = WMF_DEFAULT_SIZE; if (size_label) gtk_label_set_text (GTK_LABEL (size_label), _("WMF file does not\nspecify a size!")); } else { if (size_label) { gchar *text = g_strdup_printf (_("%d × %d"), width, height); gtk_label_set_text (GTK_LABEL (size_label), text); g_free (text); } } vals->width = width; vals->height = height; return success; }
static guchar * wmf_get_pixbuf (const gchar *filename, gint *width, gint *height) { GMappedFile *file; guchar *pixels = NULL; /* the bits we need to decode the WMF via libwmf2's GD layer */ wmf_error_t err; gulong flags; wmf_gd_t *ddata = NULL; wmfAPI *API = NULL; wmfAPI_Options api_options; guint file_width; guint file_height; wmfD_Rect bbox; gint *gd_pixels = NULL; file = g_mapped_file_new (filename, FALSE, NULL); if (! file) return NULL; flags = WMF_OPT_IGNORE_NONFATAL | WMF_OPT_FUNCTION; api_options.function = wmf_gd_function; err = wmf_api_create (&API, flags, &api_options); if (err != wmf_E_None) goto _wmf_error; ddata = WMF_GD_GetData (API); ddata->type = wmf_gd_image; err = wmf_mem_open (API, (guchar *) g_mapped_file_get_contents (file), g_mapped_file_get_length (file)); if (err != wmf_E_None) goto _wmf_error; err = wmf_scan (API, 0, &bbox); if (err != wmf_E_None) goto _wmf_error; err = wmf_display_size (API, &file_width, &file_height, WMF_DEFAULT_RESOLUTION, WMF_DEFAULT_RESOLUTION); if (err != wmf_E_None || file_width <= 0 || file_height <= 0) goto _wmf_error; if (!*width || !*height) goto _wmf_error; /* either both arguments negative or none */ if ((*width * *height) < 0) goto _wmf_error; ddata->bbox = bbox; if (*width > 0) { ddata->width = *width; ddata->height = *height; } else { gdouble w = file_width; gdouble h = file_height; gdouble aspect = ((gdouble) *width) / (gdouble) *height; if (aspect > (w / h)) { ddata->height = abs (*height); ddata->width = (gdouble) abs (*width) * (w / h) + 0.5; } else { ddata->width = abs (*width); ddata->height = (gdouble) abs (*height) / (w / h) + 0.5; } } err = wmf_play (API, 0, &bbox); if (err != wmf_E_None) goto _wmf_error; if (ddata->gd_image != NULL) gd_pixels = wmf_gd_image_pixels (ddata->gd_image); if (gd_pixels == NULL) goto _wmf_error; pixels = pixbuf_gd_convert (gd_pixels, ddata->width, ddata->height); if (pixels == NULL) goto _wmf_error; *width = ddata->width; *height = ddata->height; _wmf_error: if (API) { wmf_mem_close (API); wmf_api_destroy (API); } g_mapped_file_unref (file); return pixels; }
static gboolean gdk_pixbuf__wmf_image_stop_load (gpointer data, GError **error) { /* will be used to represent the WMF in-memory * during the decoding process */ WmfContext *context = (WmfContext *)data; gboolean result = FALSE; guchar *pixels = NULL; GdkPixbuf *pixbuf = NULL; /* the bits we need to decode the WMF via libwmf2's GD layer */ wmf_error_t err; unsigned long flags; wmf_gd_t *ddata = NULL; wmfAPI *API = NULL; wmfAPI_Options api_options; wmfD_Rect bbox; int *gd_pixels = NULL; /* the natural width and height of the WMF or the user-specified with+height */ gint width, height; double resolution_x, resolution_y; if (error != NULL) *error = NULL; /* TODO: be smarter about getting the resolution from screen */ resolution_x = resolution_y = 72.0; width = height = -1; flags = WMF_OPT_IGNORE_NONFATAL | WMF_OPT_FUNCTION; api_options.function = wmf_gd_function; err = wmf_api_create (&API, flags, &api_options); if (err != wmf_E_None) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, "Couldn't create WMF reader"); goto _wmf_error; } ddata = WMF_GD_GetData (API); ddata->type = wmf_gd_image; err = wmf_mem_open (API, context->data->data, context->data->len); if (err != wmf_E_None) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, "Couldn't create reader API"); goto _wmf_error; } err = wmf_scan (API, 0, &bbox); if (err != wmf_E_None) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, "Error scanning WMF file"); goto _wmf_error; } /* find out how large the app wants the pixbuf to be */ if (context->size_func != NULL) (*context->size_func) (&width, &height, context->user_data); /* if these are <= 0, assume user wants the natural size of the wmf */ if (width <= 0 || height <= 0) { err = wmf_display_size (API, &width, &height, resolution_x, resolution_y); if (err != wmf_E_None || width <= 0 || height <= 0) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, "Couldn't determine image size"); goto _wmf_error; } } ddata->bbox = bbox; ddata->width = width; ddata->height = height; err = wmf_play (API, 0, &bbox); if (err != wmf_E_None) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, "Couldn't decode WMF file into pixbuf"); goto _wmf_error; } wmf_mem_close (API); if (ddata->gd_image != NULL) gd_pixels = wmf_gd_image_pixels (ddata->gd_image); if (gd_pixels == NULL) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, "Couldn't decode WMF file - no output (huh?)"); goto _wmf_error; } pixels = pixbuf_gd_convert (gd_pixels, width, height); if (pixels == NULL) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, "Couldn't create RGBA buffer"); goto _wmf_error; } wmf_api_destroy (API); API = NULL; pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8, width, height, width * 4, pixbuf_destroy_function, NULL); if (pixbuf == NULL) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, "Couldn't decode WMF file"); goto _wmf_error; } if (context->prepared_func != NULL) (* context->prepared_func) (pixbuf, NULL, context->user_data); if (context->updated_func != NULL) (* context->updated_func) (pixbuf, 0, 0, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf), context->user_data); result = TRUE; _wmf_error: if (API != NULL) wmf_api_destroy (API); g_byte_array_free (context->data, TRUE); g_free (context); return result; }