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: Mon, 20 Aug 2007 11:31:20 +0200 Message-ID: References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: sea.gmane.org 1187608577 24646 80.91.229.12 (20 Aug 2007 11:16:17 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Mon, 20 Aug 2007 11:16:17 +0000 (UTC) To: emacs-devel Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Aug 20 13:16:15 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 1IN5Es-0008SL-MX for ged-emacs-devel@m.gmane.org; Mon, 20 Aug 2007 13:16:07 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1IN5Eu-0001Gz-6T for ged-emacs-devel@m.gmane.org; Mon, 20 Aug 2007 07:16:08 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1IN5Eo-0001DL-Aa for emacs-devel@gnu.org; Mon, 20 Aug 2007 07:16:02 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1IN5Em-0001CB-KR for emacs-devel@gnu.org; Mon, 20 Aug 2007 07:16:01 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1IN5Em-0001C8-Dd for emacs-devel@gnu.org; Mon, 20 Aug 2007 07:16:00 -0400 Original-Received: from proxy3.bredband.net ([195.54.101.73]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1IN5Ej-0003pr-Mt for emacs-devel@gnu.org; Mon, 20 Aug 2007 07:15:58 -0400 Original-Received: from kurono.home (83.227.131.3) by proxy3.bredband.net (7.3.127) id 46C95CC10000001B for emacs-devel@gnu.org; Mon, 20 Aug 2007 11:31:22 +0200 In-Reply-To: (Richard Stallman's message of "Sun\, 19 Aug 2007 18\:30\:43 -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:76823 Archived-At: --=-=-= Richard Stallman writes: > The code is now ready for installation. Thank you. > To install it requires a change log entry, and a NEWS entry. Ok, heres a new version of the patch, and a NEWS entry that was agreed upon earlier. I suppose the committer provides a changelog entry? Please remember that Paul Pogonyshev is the author of the patch, I've just cleaned it up a bit. NEWS entry: ** Support for SVG images Emacs now supports the SVG image format through librsvg2. Patch: --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=svg.patch ? emacs_svg.patch Index: configure.in =================================================================== RCS file: /sources/emacs/emacs/configure.in,v retrieving revision 1.459 diff -u -p -r1.459 configure.in --- configure.in 26 Jul 2007 05:26:01 -0000 1.459 +++ configure.in 20 Aug 2007 08:47:43 -0000 @@ -110,10 +110,12 @@ AC_ARG_WITH(png, [ --with-png use -lpng for displaying PNG images]) AC_ARG_WITH(gpm, [ --with-gpm use -lgpm for mouse support on a GNU/Linux console]) +AC_ARG_WITH(rsvg, +[ --with-rsvg use -lrsvg-2 for displaying SVG images]) AC_ARG_WITH(gtk, [ --with-gtk use GTK (same as --with-x-toolkit=gtk)]) AC_ARG_WITH(pkg-config-prog, -[ --with-pkg-config-prog Path to pkg-config to use for finding GTK]) +[ --with-pkg-config-prog Path to pkg-config to use for finding GTK and librsvg]) AC_ARG_WITH(toolkit-scroll-bars, [ --without-toolkit-scroll-bars don't use Motif or Xaw3d scroll bars]) @@ -2122,6 +2124,32 @@ fail; fi fi +### Use -lrsvg-2 if available, unless `--with-rsvg=no' is specified. +HAVE_RSVG=no +if test "${HAVE_X11}" = "yes"; then + if test "${with_rsvg}" != "no"; then + dnl Check if `--with-pkg-config-prog' has been given. + if test "X${with_pkg_config_prog}" != X; then + PKG_CONFIG="${with_pkg_config_prog}" + fi + + RSVG_REQUIRED=2.0.0 + RSVG_MODULE="librsvg-2.0 >= $RSVG_REQUIRED" + + PKG_CHECK_MODULES(RSVG, $RSVG_MODULE, :, :) + AC_SUBST(RSVG_CFLAGS) + AC_SUBST(RSVG_LIBS) + + if test ".${RSVG_CFLAGS}" != "."; then + HAVE_RSVG=yes + AC_DEFINE(HAVE_RSVG, 1, [Define to 1 if using librsvg.]) + CFLAGS="$CFLAGS $RSVG_CFLAGS" + LIBS="$RSVG_LIBS $LIBS" + fi + fi +fi + + HAVE_GTK=no if test "${with_gtk}" = "yes" && test "$USE_X_TOOLKIT" = "gtk"; then USE_X_TOOLKIT=none @@ -3362,6 +3390,7 @@ echo " Does Emacs use -ljpeg? echo " Does Emacs use -ltiff? ${HAVE_TIFF}" echo " Does Emacs use a gif library? ${HAVE_GIF} $ac_gif_lib_name" echo " Does Emacs use -lpng? ${HAVE_PNG}" +echo " Does Emacs use -lrsvg-2? ${HAVE_RSVG}" echo " Does Emacs use -lgpm? ${HAVE_GPM}" echo " Does Emacs use X toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS}" echo Index: lisp/image-file.el =================================================================== RCS file: /sources/emacs/emacs/lisp/image-file.el,v retrieving revision 1.29 diff -u -p -r1.29 image-file.el --- lisp/image-file.el 26 Jul 2007 05:26:26 -0000 1.29 +++ lisp/image-file.el 20 Aug 2007 08:48:30 -0000 @@ -39,7 +39,7 @@ ;;;###autoload (defcustom image-file-name-extensions - '("png" "jpeg" "jpg" "gif" "tiff" "tif" "xbm" "xpm" "pbm" "pgm" "ppm" "pnm") + '("png" "jpeg" "jpg" "gif" "tiff" "tif" "xbm" "xpm" "pbm" "pgm" "ppm" "pnm" "svg") "*A list of image-file filename extensions. Filenames having one of these extensions are considered image files, in addition to those matching `image-file-name-regexps'. Index: lisp/image.el =================================================================== RCS file: /sources/emacs/emacs/lisp/image.el,v retrieving revision 1.72 diff -u -p -r1.72 image.el --- lisp/image.el 26 Jul 2007 05:26:26 -0000 1.72 +++ lisp/image.el 20 Aug 2007 08:48:30 -0000 @@ -43,7 +43,8 @@ static char \\1_bits" . xbm) ("\\`\\(?:MM\0\\*\\|II\\*\0\\)" . tiff) ("\\`[\t\n\r ]*%!PS" . postscript) - ("\\`\xff\xd8" . (image-jpeg-p . jpeg))) + ("\\`\xff\xd8" . (image-jpeg-p . jpeg)) + ("\\`<\\?xml " . svg)) "Alist of (REGEXP . IMAGE-TYPE) pairs used to auto-detect image types. When the first bytes of an image file match REGEXP, it is assumed to be of image type IMAGE-TYPE if IMAGE-TYPE is a symbol. If not a symbol, Index: src/Makefile.in =================================================================== RCS file: /sources/emacs/emacs/src/Makefile.in,v retrieving revision 1.346 diff -u -p -r1.346 Makefile.in --- src/Makefile.in 26 Jul 2007 05:27:47 -0000 1.346 +++ src/Makefile.in 20 Aug 2007 08:49:46 -0000 @@ -281,7 +281,7 @@ TOOLKIT_DEFINES = /* C_SWITCH_X_SITE must come before C_SWITCH_X_MACHINE and C_SWITCH_X_SYSTEM since it may have -I options that should override those two. */ -ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(TOOLKIT_DEFINES) $(MYCPPFLAGS) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_SITE C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM C_SWITCH_SYSTEM_TEMACS ${CFLAGS_SOUND} ${CFLAGS} +ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(TOOLKIT_DEFINES) $(MYCPPFLAGS) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_SITE @RSVG_CFLAGS@ C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM C_SWITCH_SYSTEM_TEMACS ${CFLAGS_SOUND} ${CFLAGS} .c.o: $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $< @@ -450,7 +450,7 @@ XFT_LIBS=@XFT_LIBS@ /* LD_SWITCH_X_DEFAULT comes after everything else that specifies options for where to find X libraries, but before those libraries. */ X11_LDFLAGS = LD_SWITCH_X_SITE LD_SWITCH_X_DEFAULT -LIBX= $(LIBXMENU) $(X11_LDFLAGS) $(LIBXT) LIBTIFF LIBJPEG LIBPNG LIBGIF LIBXPM LIB_X11_LIB LIBX11_MACHINE LIBX11_SYSTEM $(XFT_LIBS) +LIBX= $(LIBXMENU) $(X11_LDFLAGS) $(LIBXT) LIBTIFF LIBJPEG LIBPNG LIBGIF LIBXPM @RSVG_LIBS@ LIB_X11_LIB LIBX11_MACHINE LIBX11_SYSTEM $(XFT_LIBS) #else /* not HAVE_X11 */ LIBX= $(LIBXMENU) LD_SWITCH_X_SITE -lX10 LIBX10_MACHINE LIBX10_SYSTEM #endif /* not HAVE_X11 */ Index: src/image.c =================================================================== RCS file: /sources/emacs/emacs/src/image.c,v retrieving revision 1.77 diff -u -p -r1.77 image.c --- src/image.c 7 Aug 2007 16:25:26 -0000 1.77 +++ src/image.c 20 Aug 2007 08:49:50 -0000 @@ -8199,6 +8199,329 @@ gif_load (f, img) #endif /* HAVE_GIF */ + +/*********************************************************************** + 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'. Its the same type of + structure defined for all image formats, handled by emacs image + functions. See struct image_type in dispextern.h. */ + +static struct image_type svg_type = +{ + /* An identifier showing that this is an image structure for the SVG format. */ + &Qsvg, + /* Handle to a function that can be used to identify a SVG file. */ + svg_image_p, + /* Handle to function used to load a SVG file. */ + svg_load, + /* Handle to function to free sresources for SVG. */ + x_clear_image, + /* An internal field to link to the next image type in a list of + image types, will be filled in when registering the format. */ + NULL +}; + + +/* Return non-zero if OBJECT is a valid SVG image specification. Do + this by calling parse_image_spec and supplying the keywords that + identify the SVG format. */ + +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 + +/* TO DO: define DEF_IMGLIB_FN here. This macro is used to handle +loading of dynamic link library functions for various OS:es. +Currently only librsvg2 is supported, which is only available for X, +so its not strictly necessary yet. The current code is thought to be +compatible with this scheme because of the defines below, should +librsvg2 become available on more plattforms. */ + +#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. this function will go into the svg_type structure, and + the prototype thus needs to be compatible with that structure. */ + +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; + } + + /* Read the entire file into memory. */ + contents = slurp_file (SDATA (file), &size); + if (contents == NULL) + { + image_error ("Error loading SVG image `%s'", img->spec, Qnil); + UNGCPRO; + return 0; + } + /* If the file was slurped into memory properly, parse it. */ + success_p = svg_load_image (f, img, contents, size); + xfree (contents); + UNGCPRO; + } + /* Else its not a file, its a lisp object. Load the image from a + lisp object rather than a file. */ + 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; +} + +/* svg_load_image is a helper function for svg_load, which 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) + /* Pointer to emacs frame sturcture. */ + struct frame *f; + /* Pointer to emacs image structure. */ + struct image *img; + /* String containing the SVG XML data to be parsed. */ + unsigned char *contents; + /* Size of data in bytes. */ + 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 is a glib function that must be called prior to using + gnome type library functions. */ + g_type_init (); + /* Make a handle to a new rsvg object. */ + rsvg_handle = fn_rsvg_handle_new (); + + /* Parse the contents argument and fill in the rsvg_handle. */ + fn_rsvg_handle_write (rsvg_handle, contents, size, &error); + if (error) + goto rsvg_error; + + /* The parsing is complete, rsvg_handle is ready to used, close it + for further writes. */ + fn_rsvg_handle_close (rsvg_handle, &error); + if (error) + goto rsvg_error; + /* We can now get a valid pixel buffer from the svg file, if all + went ok. */ + pixbuf = fn_rsvg_handle_get_pixbuf (rsvg_handle); + eassert (pixbuf); + + /* Extract some meta data from the svg handle. */ + 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); + + /* Validate the svg meta data. */ + 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); + + /* Try to create a x pixmap to hold the svg pixmap. */ + if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) { + g_object_unref (pixbuf); + return 0; + } + + init_color_table (); + + /* TODO: The code is somewhat prepared for other environments than + X, but is far from done. */ +#ifdef HAVE_X_WINDOWS + + background.pixel = FRAME_BACKGROUND_PIXEL (f); + x_query_color (f, &background); + + /* SVG pixmaps specify transparency in the last byte, so right shift + 8 bits to get rid of it, since emacs doesnt support + transparency. */ + 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. Each pixel must be "flattened" by + calculating he resulting color, given the transparency of the + pixel, and the image background color. */ + 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 so the user knows what is the actual + problem with the image. */ + image_error ("Error parsing SVG image `%s'", img->spec, Qnil); + g_error_free (error); + return 0; +} + +#endif /* defined (HAVE_RSVG) */ + + + /*********************************************************************** Ghostscript @@ -8591,6 +8914,11 @@ of `image-library-alist', which see). * return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries); #endif +#if defined (HAVE_RSVG) + if (EQ (type, Qsvg)) + return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries); +#endif + #ifdef HAVE_GHOSTSCRIPT if (EQ (type, Qpostscript)) return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries); @@ -8733,6 +9061,13 @@ non-numeric, there is no explicit limit ADD_IMAGE_TYPE(Qpng); #endif +#if defined (HAVE_RSVG) + Qsvg = intern ("svg"); + staticpro (&Qsvg); + ADD_IMAGE_TYPE(Qsvg); +#endif + + defsubr (&Sinit_image_library); defsubr (&Sclear_image_cache); defsubr (&Simage_refresh); --=-=-= -- Joakim Verona --=-=-= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Emacs-devel mailing list Emacs-devel@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-devel --=-=-=--