static void get_property (GObject * instance, guint prop_id, GValue * value, GParamSpec * pspec) { RsvgHandle *self = RSVG_HANDLE (instance); RsvgDimensionData dim; switch (prop_id) { case PROP_DPI_X: g_value_set_double (value, self->priv->dpi_x); break; case PROP_DPI_Y: g_value_set_double (value, self->priv->dpi_y); break; case PROP_BASE_URI: g_value_set_string (value, rsvg_handle_get_base_uri (self)); break; case PROP_WIDTH: rsvg_handle_get_dimensions (self, &dim); g_value_set_int (value, dim.width); break; case PROP_HEIGHT: rsvg_handle_get_dimensions (self, &dim); g_value_set_int (value, dim.height); break; case PROP_EM: rsvg_handle_get_dimensions (self, &dim); g_value_set_double (value, dim.em); break; case PROP_EX: rsvg_handle_get_dimensions (self, &dim); g_value_set_double (value, dim.ex); break; case PROP_TITLE: g_value_set_string (value, rsvg_handle_get_title (self)); break; case PROP_DESC: g_value_set_string (value, rsvg_handle_get_desc (self)); break; case PROP_METADATA: g_value_set_string (value, rsvg_handle_get_metadata (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (instance, prop_id, pspec); } }
static GstFlowReturn gst_rsvg_decode_image (GstRsvgDec * rsvg, const guint8 * data, guint size, GstBuffer ** buffer) { GstFlowReturn ret = GST_FLOW_OK; cairo_t *cr; cairo_surface_t *surface; RsvgHandle *handle; GError *error = NULL; RsvgDimensionData dimension; gdouble scalex, scaley; const gchar *title = NULL, *comment = NULL; GST_LOG_OBJECT (rsvg, "parsing svg"); handle = rsvg_handle_new_from_data (data, size, &error); if (!handle) { GST_ERROR_OBJECT (rsvg, "Failed to parse SVG image: %s", error->message); g_error_free (error); return GST_FLOW_ERROR; } title = rsvg_handle_get_title (handle); comment = rsvg_handle_get_desc (handle); if (title || comment) { GST_LOG_OBJECT (rsvg, "adding tags"); if (!rsvg->pending_tags) rsvg->pending_tags = gst_tag_list_new (); if (title && *title) gst_tag_list_add (rsvg->pending_tags, GST_TAG_MERGE_REPLACE_ALL, GST_TAG_TITLE, title, NULL); if (comment && *comment) gst_tag_list_add (rsvg->pending_tags, GST_TAG_MERGE_REPLACE_ALL, GST_TAG_COMMENT, comment, NULL); } rsvg_handle_get_dimensions (handle, &dimension); if (rsvg->width != dimension.width || rsvg->height != dimension.height) { GstCaps *caps1, *caps2, *caps3; GstStructure *s; GST_LOG_OBJECT (rsvg, "resolution changed, updating caps"); caps1 = gst_caps_copy (gst_pad_get_pad_template_caps (rsvg->srcpad)); caps2 = gst_pad_peer_get_caps (rsvg->srcpad); if (caps2) { caps3 = gst_caps_intersect (caps1, caps2); gst_caps_unref (caps1); gst_caps_unref (caps2); caps1 = caps3; caps3 = NULL; } if (gst_caps_is_empty (caps1)) { GST_ERROR_OBJECT (rsvg, "Unable to negotiate a format"); gst_caps_unref (caps1); g_object_unref (handle); return GST_FLOW_NOT_NEGOTIATED; } caps2 = gst_caps_copy (gst_pad_get_pad_template_caps (rsvg->srcpad)); s = gst_caps_get_structure (caps2, 0); gst_structure_set (s, "width", G_TYPE_INT, dimension.width, "height", G_TYPE_INT, dimension.height, "framerate", GST_TYPE_FRACTION, 0, 1, NULL); caps3 = gst_caps_intersect (caps1, caps2); if (!gst_caps_is_empty (caps3)) { gst_caps_truncate (caps3); gst_pad_set_caps (rsvg->srcpad, caps3); gst_caps_unref (caps1); gst_caps_unref (caps2); gst_caps_unref (caps3); rsvg->width = dimension.width; rsvg->height = dimension.height; } else { gst_caps_unref (caps2); gst_caps_unref (caps3); gst_caps_truncate (caps1); s = gst_caps_get_structure (caps1, 0); gst_structure_set (s, "framerate", GST_TYPE_FRACTION, 0, 1, NULL); if (!gst_caps_is_fixed (caps1) && (!gst_structure_fixate_field_nearest_int (s, "width", dimension.width) || !gst_structure_fixate_field_nearest_int (s, "height", dimension.height))) { g_object_unref (handle); GST_ERROR_OBJECT (rsvg, "Failed to fixate caps"); return GST_FLOW_NOT_NEGOTIATED; } gst_pad_set_caps (rsvg->srcpad, caps1); gst_structure_get_int (s, "width", &rsvg->width); gst_structure_get_int (s, "height", &rsvg->height); gst_caps_unref (caps1); } } if ((ret = gst_pad_alloc_buffer_and_set_caps (rsvg->srcpad, GST_BUFFER_OFFSET_NONE, rsvg->width * rsvg->height * 4, GST_PAD_CAPS (rsvg->srcpad), buffer)) != GST_FLOW_OK) { g_object_unref (handle); GST_ERROR_OBJECT (rsvg, "Buffer allocation failed %s", gst_flow_get_name (ret)); return ret; } GST_LOG_OBJECT (rsvg, "render image at %d x %d", rsvg->height, rsvg->width); surface = cairo_image_surface_create_for_data (GST_BUFFER_DATA (*buffer), CAIRO_FORMAT_ARGB32, rsvg->width, rsvg->height, rsvg->width * 4); cr = cairo_create (surface); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); cairo_paint (cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0); scalex = scaley = 1.0; if (rsvg->width != dimension.width) { scalex = ((gdouble) rsvg->width) / ((gdouble) dimension.width); } if (rsvg->height != dimension.height) { scaley = ((gdouble) rsvg->height) / ((gdouble) dimension.height); } cairo_scale (cr, scalex, scaley); rsvg_handle_render_cairo (handle, cr); g_object_unref (handle); cairo_destroy (cr); cairo_surface_destroy (surface); /* Now unpremultiply Cairo's ARGB to match GStreamer's */ gst_rsvg_decode_unpremultiply (GST_BUFFER_DATA (*buffer), rsvg->width, rsvg->height); return ret; }
static VALUE rb_rsvg_handle_get_desc(VALUE self) { return CSTR2RVAL(rsvg_handle_get_desc(_SELF(self))); }