static void
gnm_soi_copy (SheetObject *dst, SheetObject const *src)
{
	SheetObjectImage const *soi = SHEET_OBJECT_IMAGE (src);
	SheetObjectImage   *new_soi = SHEET_OBJECT_IMAGE (dst);

	new_soi->type		= g_strdup (soi->type);
	new_soi->bytes.len	= soi->bytes.len;
	new_soi->bytes.data	= g_memdup (soi->bytes.data, soi->bytes.len);
	new_soi->crop_top	= soi->crop_top;
	new_soi->crop_bottom	= soi->crop_bottom;
	new_soi->crop_left	= soi->crop_left;
	new_soi->crop_right	= soi->crop_right;
}
static SheetObjectView *
gnm_soi_new_view (SheetObject *so, SheetObjectViewContainer *container)
{
	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);
	GocItem *item = NULL;
	GdkPixbuf *pixbuf, *placeholder = NULL;

	pixbuf = soi_get_pixbuf (soi, 1.);

	if (pixbuf == NULL) {
		placeholder = gtk_icon_theme_load_icon (
			gtk_icon_theme_get_default (),
			"unknown_image", 100, 0, NULL);
		pixbuf = gdk_pixbuf_copy (placeholder);
	}

	item = goc_item_new (
		gnm_pane_object_group (GNM_PANE (container)),
		so_image_goc_view_get_type (),
		NULL);
	goc_item_hide (goc_item_new (GOC_GROUP (item),
		GOC_TYPE_PIXBUF,
		"pixbuf", pixbuf,
		NULL));
	g_object_unref (G_OBJECT (pixbuf));

	if (placeholder)
		g_object_set_data (G_OBJECT (item), "tile", placeholder);

	return gnm_pane_object_register (so, item, TRUE);
}
Beispiel #3
0
static void
gnm_soi_write_image (SheetObject const *so, char const *format, 
		     G_GNUC_UNUSED double resolution,
		     GsfOutput *output, GError **err)
{
	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);
	gboolean res = FALSE;
	GdkPixbuf *pixbuf = go_image_get_pixbuf (soi->image);

	if (!soi->type || strcmp (format, soi->type) == 0) {
		if (soi->bytes.len == 0) {
			gsize length;
			guint8 const *data = go_image_get_data (soi->image, &length);
			res = gsf_output_write (output,	length, data);
		} else
			res = gsf_output_write (output,
						soi->bytes.len, soi->bytes.data);
	} else if (pixbuf)
		res = gdk_pixbuf_save_to_callback (pixbuf,
						   soi_gdk_pixbuf_save, output,
						   format,
						   err, NULL);
	if (pixbuf)
		g_object_unref (pixbuf);
	if (!res && err && *err == NULL)
		*err = g_error_new (gsf_output_error_id (), 0,
				   _("Unknown failure while saving image"));
}
Beispiel #4
0
static void
gnm_soi_default_size (SheetObject const *so, double *w, double *h)
{
	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);
	if (soi->image) {
		*w = go_image_get_width (soi->image);
		*h = go_image_get_height (soi->image);
	} else {
		GdkPixbuf *buf = go_image_get_pixbuf (soi->image);

		if (!buf) {
			*w = *h = 5;
			return;
		}

		*w = gdk_pixbuf_get_width  (buf);
		*h = gdk_pixbuf_get_height (buf);

		/* In case buf is invalid with size 0,0 or if the image is just too
		 * small to be useful default to something slightly larger
		 * http://bugzilla.gnome.org/show_bug.cgi?id=462787
		 **/
		if ((*w * *h) < 25.) {
			if (*w < 5) *w = 25;
			if (*h < 5) *h = 25;
		}
		g_object_unref (buf);
	}
}
Beispiel #5
0
static void
gnm_soi_write_xml_sax (SheetObject const *so, GsfXMLOut *output,
		       G_GNUC_UNUSED GnmConventions const *convs)
{
	SheetObjectImage *soi;

	g_return_if_fail (IS_SHEET_OBJECT_IMAGE (so));
	soi = SHEET_OBJECT_IMAGE (so);

	gsf_xml_out_add_float (output, "crop-top", soi->crop_top, 3);
	gsf_xml_out_add_float (output, "crop-bottom", soi->crop_bottom, 3);
	gsf_xml_out_add_float (output, "crop-left", soi->crop_left, 3);
	gsf_xml_out_add_float (output, "crop-right", soi->crop_right, 3);
	gsf_xml_out_start_element (output, "Content");
	if (soi->type != NULL)
		gsf_xml_out_add_cstr (output, "image-type", soi->type);
	if (soi->image && go_image_get_name (soi->image)) {
		gsf_xml_out_add_cstr (output, "name", go_image_get_name (soi->image));
		if (sheet_object_get_sheet (so))
			go_doc_save_image (GO_DOC (sheet_object_get_sheet (so)->workbook), go_image_get_name (soi->image));
		else {
			/* looks that this may happen when pasting from another process, see #687414 */
			gsize length;
			guint8 const *data = go_image_get_data (soi->image, &length);
			gsf_xml_out_add_uint (output, "size-bytes", length);
			gsf_xml_out_add_base64 (output, NULL, data, length);
		}
	} else {
		gsf_xml_out_add_uint (output, "size-bytes", soi->bytes.len);
		gsf_xml_out_add_base64 (output, NULL, soi->bytes.data, soi->bytes.len);
	}
	gsf_xml_out_end_element (output);
}
Beispiel #6
0
static void
gnm_soi_prep_sax_parser (SheetObject *so, GsfXMLIn *xin,
			 xmlChar const **attrs,
			 G_GNUC_UNUSED GnmConventions const *convs)
{
	static GsfXMLInNode const dtd[] = {
	  GSF_XML_IN_NODE (CONTENT, CONTENT, -1, "Content", GSF_XML_CONTENT, &content_start, &content_end),
	  GSF_XML_IN_NODE_END
	};
	static GsfXMLInDoc *doc = NULL;
	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);

	if (NULL == doc)
		doc = gsf_xml_in_doc_new (dtd, NULL);
	gsf_xml_in_push_state (xin, doc, NULL, NULL, attrs);

	for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
		if (gnm_xml_attr_double (attrs, "crop-top", &soi->crop_top)) ;
		else if (gnm_xml_attr_double (attrs, "crop-bottom", &soi->crop_bottom))
			/* Nothing */ ;
		else if (gnm_xml_attr_double (attrs, "crop-left", &soi->crop_left))
			/* Nothing */ ;
		else if (gnm_xml_attr_double (attrs, "crop-right", &soi->crop_right))
			/* Nothing */ ;
	}
}
static void
gnm_soi_draw_cairo (SheetObject const *so, cairo_t *cr,
		    double width, double height)
{
	GdkPixbuf *pixbuf;
	GOImage *img;
	cairo_pattern_t *cr_pattern;
	int w, h;
	cairo_matrix_t cr_matrix;

	pixbuf = soi_get_pixbuf (SHEET_OBJECT_IMAGE (so), 1.);
	if (!pixbuf || width == 0. || height == 0.)
		return;
	cairo_save (cr);
	img = go_image_new_from_pixbuf (pixbuf);
	cr_pattern = go_image_create_cairo_pattern (img);

	w = gdk_pixbuf_get_width  (pixbuf);
	h = gdk_pixbuf_get_height (pixbuf);
	cairo_matrix_init_scale (&cr_matrix,
				 w / width,
				 h / height);
	cairo_pattern_set_matrix (cr_pattern, &cr_matrix);
	cairo_rectangle (cr, 0., 0., width, height);
	cairo_set_source (cr, cr_pattern);
	cairo_fill (cr);
	/*
	 * We need to unset the source before we destroy the pattern.
	 * cairo_restore will do that.  See #632439.
	 */
	cairo_restore (cr);
	cairo_pattern_destroy (cr_pattern);
	g_object_unref (img);
	g_object_unref (pixbuf);
}
static void
gnm_soi_get_property (GObject     *object,
		      guint        property_id,
		      GValue      *value,
		      GParamSpec  *pspec)
{
	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (object);
	GdkPixbuf *pixbuf;

	switch (property_id) {
	case PROP_IMAGE_TYPE:
		g_value_set_string (value, soi->type);
		break;
	case PROP_IMAGE_DATA:
		g_value_set_pointer (value, &soi->bytes);
		break;
	case PROP_PIXBUF:
		pixbuf = soi_get_pixbuf (soi, 1.0);
		g_value_set_object (value, pixbuf);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}
static GtkTargetList *
gnm_soi_get_target_list (SheetObject const *so)
{
	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);
	GtkTargetList *tl = gtk_target_list_new (NULL, 0);
	char *mime_str = go_image_format_to_mime (soi->type);
	GSList *mimes, *ptr;
	GdkPixbuf *pixbuf;

	mimes = go_strsplit_to_slist (mime_str, ',');
	for (ptr = mimes; ptr != NULL; ptr = ptr->next) {
		const char *mime = ptr->data;

		if (mime != NULL && *mime != '\0')
			gtk_target_list_add (tl, gdk_atom_intern (mime, FALSE),
					     0, 0);
	}
	g_free (mime_str);
	go_slist_free_custom (mimes, g_free);
	/* No need to eliminate duplicates. */
	if ((pixbuf = soi_get_pixbuf (soi, 1.0)) != NULL) {
		gtk_target_list_add_image_targets (tl, 0, TRUE);
		g_object_unref (pixbuf);
	}

	return tl;
}
Beispiel #10
0
static SheetObjectView *
gnm_soi_new_view (SheetObject *so, SheetObjectViewContainer *container)
{
	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);
	GocItem *item = NULL;

	item = goc_item_new (
		gnm_pane_object_group (GNM_PANE (container)),
		so_image_goc_view_get_type (),
		NULL);
	if (soi->image) {
		goc_item_hide (goc_item_new (GOC_GROUP (item),
			GOC_TYPE_IMAGE,
			"image", soi->image,
		        "crop-bottom", soi->crop_bottom,
		        "crop-left", soi->crop_left,
		        "crop-right", soi->crop_right,
		        "crop-top", soi->crop_top,
			NULL));

	} else {
		GdkPixbuf *placeholder = go_gdk_pixbuf_load_from_file
			("res:gnm:pixmaps/unknown_image.png");
		GdkPixbuf *pixbuf = gdk_pixbuf_copy (placeholder);

		goc_item_hide (goc_item_new (GOC_GROUP (item),
			GOC_TYPE_PIXBUF,
			"pixbuf", pixbuf,
			NULL));
		g_object_unref (pixbuf);
		g_object_set_data (G_OBJECT (item), "tile", placeholder);
	}

	return gnm_pane_object_register (so, item, TRUE);
}
static void
content_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *unknown)
{
	SheetObject *so = gnm_xml_in_cur_obj (xin);
	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);

	soi->bytes.len  = gsf_base64_decode_simple (
		xin->content->str, xin->content->len);
	soi->bytes.data = g_memdup (xin->content->str, soi->bytes.len);
}
static void
gnm_soi_finalize (GObject *object)
{
	SheetObjectImage *soi;

	soi = SHEET_OBJECT_IMAGE (object);
	g_free (soi->bytes.data);
	g_free (soi->type);
	soi->bytes.data = NULL;

	G_OBJECT_CLASS (gnm_soi_parent_class)->finalize (object);
}
static void
soi_info_cb (GdkPixbufLoader *loader,
	     int              width,
	     int              height,
	     gpointer         data)
{
	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (data);
	GdkPixbufFormat *format = gdk_pixbuf_loader_get_format (loader);
	char *name = gdk_pixbuf_format_get_name (format);

	g_free (soi->type);
	soi->type = name;
}
static void
content_start (GsfXMLIn *xin, xmlChar const **attrs)
{
	SheetObject *so = gnm_xml_in_cur_obj (xin);
	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);
	char const *image_type = NULL;

	for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
		if (attr_eq (attrs[0], "image-type"))
			image_type = CXML2C (attrs[1]);

	soi->type = g_strdup (image_type);
}
static void
gnm_soi_init (GObject *obj)
{
	SheetObjectImage *soi;
	SheetObject *so;

	soi = SHEET_OBJECT_IMAGE (obj);
	soi->dumped = FALSE;
	soi->crop_top = soi->crop_bottom = soi->crop_left = soi->crop_right
		= 0.0;

	so = SHEET_OBJECT (obj);
	so->anchor.base.direction = GOD_ANCHOR_DIR_DOWN_RIGHT;
}
Beispiel #16
0
static void
content_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *unknown)
{
	SheetObject *so = gnm_xml_in_cur_obj (xin);
	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);
	GString *data = xin->content;

	if (data->len >= 4) {
		size_t len = gsf_base64_decode_simple (data->str, data->len);
		soi->bytes.len = len;
		soi->bytes.data = g_memdup (data->str, len);
		soi->image = go_image_new_from_data (soi->type,
						     soi->bytes.data,
						     len, NULL, NULL);
	}
}
Beispiel #17
0
static void
soi_cb_save_as (SheetObject *so, SheetControl *sc)
{
	WBCGtk *wbcg;
	char *uri;
	GsfOutput *output;
	GSList *l = NULL;
	GOImageFormat sel_fmt;
	GOImageFormatInfo const *format_info;
	GdkPixbuf *pixbuf = NULL;
	GError *err = NULL;
	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);

	g_return_if_fail (soi != NULL);

	sel_fmt  = go_image_get_format_from_name (soi->type);
	if ((pixbuf = go_image_get_pixbuf (soi->image)) != NULL)
		l = go_image_get_formats_with_pixbuf_saver ();
	/* Move original format first in menu */
	if (sel_fmt != GO_IMAGE_FORMAT_UNKNOWN) {
		l = g_slist_remove (l, GUINT_TO_POINTER (sel_fmt));
		l = g_slist_prepend (l, GUINT_TO_POINTER (sel_fmt));
	}

	wbcg = scg_wbcg (SHEET_CONTROL_GUI (sc));

	uri = go_gui_get_image_save_info (wbcg_toplevel (wbcg), l, &sel_fmt, NULL);
	if (!uri)
		goto out;

	output = go_file_create (uri, &err);
	if (!output)
		goto out;
	format_info = go_image_get_format_info (sel_fmt);
	sheet_object_write_image (so, (format_info? format_info->name: NULL), -1.0, output, &err);
	gsf_output_close (output);
	g_object_unref (output);

	if (err != NULL)
		go_cmd_context_error (GO_CMD_CONTEXT (wbcg), err);

out:
	if (pixbuf)
		g_object_unref (pixbuf);
	g_free (uri);
	g_slist_free (l);
}
Beispiel #18
0
static void
gnm_soi_draw_cairo (SheetObject const *so, cairo_t *cr,
		    double width, double height)
{
	GdkPixbuf *pixbuf;
	GOImage *img;
	int w, h;
	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);

	if (soi->image) {
		w = go_image_get_width (soi->image);
		h = go_image_get_height (soi->image);
		w -= soi->crop_left - soi->crop_right;
		h -= soi->crop_top - soi->crop_bottom;
		if (w <= 0 || h <= 0)
			return;
		cairo_save (cr);
		cairo_rectangle (cr, 0, 0, width, height);
		cairo_clip (cr);
		cairo_scale (cr, width / w, height / h);
		cairo_translate (cr, -soi->crop_left, -soi->crop_top);
		go_image_draw (soi->image, cr);
		cairo_restore (cr);
	} else {
		pixbuf = go_image_get_pixbuf (soi->image);
		if (!pixbuf || width == 0. || height == 0.)
			return;
		cairo_save (cr);
		img = go_pixbuf_new_from_pixbuf (pixbuf);

		w = gdk_pixbuf_get_width  (pixbuf);
		h = gdk_pixbuf_get_height (pixbuf);
		cairo_scale (cr, width / w, height / h);
		go_image_draw (img, cr);
		/*
		 * We need to unset the source before we destroy the pattern.
		 * cairo_restore will do that.  See #632439.
		 */
		cairo_restore (cr);
		g_object_unref (img);
		g_object_unref (pixbuf);
	}
}
static void
gnm_soi_write_xml_sax (SheetObject const *so, GsfXMLOut *output,
		       GnmConventions const *convs)
{
	SheetObjectImage *soi;

	g_return_if_fail (IS_SHEET_OBJECT_IMAGE (so));
	soi = SHEET_OBJECT_IMAGE (so);

	gsf_xml_out_add_float (output, "crop-top", soi->crop_top, 3);
	gsf_xml_out_add_float (output, "crop-bottom", soi->crop_bottom, 3);
	gsf_xml_out_add_float (output, "crop-left", soi->crop_left, 3);
	gsf_xml_out_add_float (output, "crop-right", soi->crop_right, 3);
	gsf_xml_out_start_element (output, "Content");
	if (soi->type != NULL)
		gsf_xml_out_add_cstr (output, "image-type", soi->type);
	gsf_xml_out_add_uint (output, "size-bytes", soi->bytes.len);
	gsf_xml_out_add_base64 (output, NULL, soi->bytes.data, soi->bytes.len);
	gsf_xml_out_end_element (output);
}
Beispiel #20
0
static gboolean
gnm_soi_assign_to_sheet (SheetObject *so, Sheet *sheet)
{
	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);

	if (soi->image/* && !go_image_get_name (soi->image)*/) {
		GODoc *doc = GO_DOC (sheet->workbook);
		GOImage *image = go_doc_add_image (doc, soi->name, soi->image);
		if (soi->image != image) {
			g_object_unref (soi->image);
			soi->image = g_object_ref (image);
		}
	} else if (soi->name) {
		GODoc *doc = GO_DOC (sheet->workbook);
		GType type = go_image_type_for_format (soi->type);
		if (type != 0)
			soi->image = g_object_ref (go_doc_image_fetch (doc, soi->name, type));
	} else {
		/* There is nothing we can do */
	}
	return FALSE;
}
static void
gnm_soi_write_image (SheetObject const *so, char const *format, double resolution,
		     GsfOutput *output, GError **err)
{
	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);
	gboolean res = FALSE;
	GdkPixbuf *pixbuf = soi_get_pixbuf (soi, 1.0);

	if (strcmp (format, soi->type) == 0)
		res = gsf_output_write (output,
					soi->bytes.len, soi->bytes.data);
	else if (pixbuf)
		res = gdk_pixbuf_save_to_callback (pixbuf,
						   soi_gdk_pixbuf_save, output,
						   format,
						   err, NULL);
	if (pixbuf)
		g_object_unref (pixbuf);
	if (!res && err && *err == NULL)
		*err = g_error_new (gsf_output_error_id (), 0,
				   _("Unknown failure while saving image"));
}