From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: joakim@verona.se Newsgroups: gmane.emacs.devel Subject: Re: SVG support(again) ? Date: Thu, 16 Aug 2007 11:03:01 +0200 Message-ID: References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sea.gmane.org 1187255004 3845 80.91.229.12 (16 Aug 2007 09:03:24 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Thu, 16 Aug 2007 09:03:24 +0000 (UTC) To: emacs-devel Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Aug 16 11:03:21 2007 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1ILbGD-0000wG-9W for ged-emacs-devel@m.gmane.org; Thu, 16 Aug 2007 11:03:21 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1ILbGC-0001zn-7T for ged-emacs-devel@m.gmane.org; Thu, 16 Aug 2007 05:03:20 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1ILbFz-0001yl-GY for emacs-devel@gnu.org; Thu, 16 Aug 2007 05:03:07 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1ILbFx-0001xb-DC for emacs-devel@gnu.org; Thu, 16 Aug 2007 05:03:06 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1ILbFx-0001xP-1p for emacs-devel@gnu.org; Thu, 16 Aug 2007 05:03:05 -0400 Original-Received: from proxy2.bredband.net ([195.54.101.72]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1ILbFw-0000iW-7N for emacs-devel@gnu.org; Thu, 16 Aug 2007 05:03:04 -0400 Original-Received: from kurono.home (83.227.131.3) by proxy2.bredband.net (7.3.127) id 46BC722D001897BD for emacs-devel@gnu.org; Thu, 16 Aug 2007 11:03:02 +0200 In-Reply-To: (Richard Stallman's message of "Tue\, 14 Aug 2007 19\:26\:16 -0400") User-Agent: Gnus/5.110006 (No Gnus v0.6) Emacs/22.1.50 (gnu/linux) X-Detected-Kernel: Genre and OS details not recognized. X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:76620 Archived-At: Richard Stallman writes: > - Is this text for NEWS ok? > > ** Support for SVG images > > Emacs now supports the SVG image format through librsvg2. > > Yes, it is good enough. > > - I looked through the code briefly, and it didnt seem too bad on the > commenting. Was it anything in particular you thought needed clarification? > > There are functions that don't even have a comment at the beginning to > say what they do and how to call them. It needs a lot of improvement > in comments. I did some commenting in the SVG handler part of image.c below. The code seems to be mostly the same as for other image formats in image.c. Is it ok to discuss this part of the patch like this, and then I can supply a new combined patch for consideration? (again, I'm not the patchs original author, I'm just trying to help out to get it clean enough for inclusion.) /*********************************************************************** SVG ***********************************************************************/ #if defined (HAVE_RSVG) /* Function prototypes. */ static int svg_image_p P_ ((Lisp_Object object)); static int svg_load P_ ((struct frame *f, struct image *img)); static int svg_load_image P_ ((struct frame *, struct image *, unsigned char *, unsigned int)); /* The symbol `svg' identifying images of this type. */ Lisp_Object Qsvg; /* Indices of image specification fields in svg_format, below. */ enum svg_keyword_index { SVG_TYPE, SVG_DATA, SVG_FILE, SVG_ASCENT, SVG_MARGIN, SVG_RELIEF, SVG_ALGORITHM, SVG_HEURISTIC_MASK, SVG_MASK, SVG_BACKGROUND, SVG_LAST }; /* Vector of image_keyword structures describing the format of valid user-defined image specifications. */ static struct image_keyword svg_format[SVG_LAST] = { {":type", IMAGE_SYMBOL_VALUE, 1}, {":data", IMAGE_STRING_VALUE, 0}, {":file", IMAGE_STRING_VALUE, 0}, {":ascent", IMAGE_ASCENT_VALUE, 0}, {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, {":relief", IMAGE_INTEGER_VALUE, 0}, {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; /* Structure describing the image type `svg'. */ static struct image_type svg_type = { &Qsvg, svg_image_p, svg_load, x_clear_image, NULL }; /* Return non-zero if OBJECT is a valid SVG image specification. */ static int svg_image_p (object) Lisp_Object object; { struct image_keyword fmt[SVG_LAST]; bcopy (svg_format, fmt, sizeof fmt); if (!parse_image_spec (object, fmt, SVG_LAST, Qsvg)) return 0; /* Must specify either the :data or :file keyword. */ return fmt[SVG_FILE].count + fmt[SVG_DATA].count == 1; } #include /* DEF_IMGLIB_FN() here? */ #define fn_rsvg_handle_new rsvg_handle_new #define fn_rsvg_handle_set_size_callback rsvg_handle_set_size_callback #define fn_rsvg_handle_write rsvg_handle_write #define fn_rsvg_handle_close rsvg_handle_close #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf #define fn_rsvg_handle_free rsvg_handle_free #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample /* Load SVG image IMG for use on frame F. Value is non-zero if successful. */ static int svg_load (f, img) struct frame *f; struct image *img; { int success_p = 0; Lisp_Object file_name; /* If IMG->spec specifies a file name, create a non-file spec from it. */ file_name = image_spec_value (img->spec, QCfile, NULL); if (STRINGP (file_name)) { Lisp_Object file; unsigned char *contents; int size; struct gcpro gcpro1; file = x_find_image_file (file_name); GCPRO1 (file); if (!STRINGP (file)) { image_error ("Cannot find image file `%s'", file_name, Qnil); UNGCPRO; return 0; } contents = slurp_file (SDATA (file), &size); if (contents == NULL) { image_error ("Error loading SVG image `%s'", img->spec, Qnil); UNGCPRO; return 0; } success_p = svg_load_image (f, img, contents, size); xfree (contents); UNGCPRO; } else { Lisp_Object data; data = image_spec_value (img->spec, QCdata, NULL); success_p = svg_load_image (f, img, SDATA (data), SBYTES (data)); } return success_p; } /* helper function for svg_load, does the actual loading given contents and size, apart from frame and image structures, passed from svg_load Uses librsvg to do most of the image processing. Returns non-zero when sucessful */ static int svg_load_image (f, img, contents, size) struct frame *f; struct image *img; unsigned char *contents; unsigned int size; { RsvgHandle *rsvg_handle; GError *error = NULL; GdkPixbuf *pixbuf; int width; int height; const guint8 *pixels; int rowstride; XImagePtr ximg; XColor background; int x; int y; g_type_init (); rsvg_handle = fn_rsvg_handle_new (); fn_rsvg_handle_write (rsvg_handle, contents, size, &error); if (error) goto rsvg_error; fn_rsvg_handle_close (rsvg_handle, &error); if (error) goto rsvg_error; pixbuf = fn_rsvg_handle_get_pixbuf (rsvg_handle); eassert (pixbuf); width = fn_gdk_pixbuf_get_width (pixbuf); height = fn_gdk_pixbuf_get_height (pixbuf); pixels = fn_gdk_pixbuf_get_pixels (pixbuf); rowstride = fn_gdk_pixbuf_get_rowstride (pixbuf); eassert (fn_gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB); eassert (fn_gdk_pixbuf_get_n_channels (pixbuf) == 4); eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf)); eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf) == 8); if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) { g_object_unref (pixbuf); return 0; } init_color_table (); #ifdef HAVE_X_WINDOWS background.pixel = FRAME_BACKGROUND_PIXEL (f); x_query_color (f, &background); background.red >>= 8; background.green >>= 8; background.blue >>= 8; #else /* not HAVE_X_WINDOWS */ #error FIXME #endif /* this loop handles opacity values, since emacs assumes non-transparent images. */ for (y = 0; y < height; ++y) { for (x = 0; x < width; ++x) { unsigned red; unsigned green; unsigned blue; unsigned opacity; red = *pixels++; green = *pixels++; blue = *pixels++; opacity = *pixels++; red = ((red * opacity) + (background.red * ((1 << 8) - opacity))); green = ((green * opacity) + (background.green * ((1 << 8) - opacity))); blue = ((blue * opacity) + (background.blue * ((1 << 8) - opacity))); XPutPixel (ximg, x, y, lookup_rgb_color (f, red, green, blue)); } pixels += rowstride - 4 * width; } #ifdef COLOR_TABLE_SUPPORT /* Remember colors allocated for this image. */ img->colors = colors_in_color_table (&img->ncolors); free_color_table (); #endif /* COLOR_TABLE_SUPPORT */ g_object_unref (pixbuf); /* Put the image into the pixmap, then free the X image and its buffer. */ x_put_x_image (f, ximg, img->pixmap, width, height); x_destroy_x_image (ximg); img->width = width; img->height = height; return 1; rsvg_error: /* FIXME: Use error->message. */ image_error ("Error parsing SVG image `%s'", img->spec, Qnil); g_error_free (error); return 0; } #endif /* defined (HAVE_RSVG) */ -- Joakim Verona