[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: SVG support(again) ?
From: |
joakim |
Subject: |
Re: SVG support(again) ? |
Date: |
Mon, 20 Aug 2007 11:31:20 +0200 |
User-agent: |
Gnus/5.110006 (No Gnus v0.6) Emacs/22.1.50 (gnu/linux) |
Richard Stallman <address@hidden> 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:
? 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 @@ address@hidden@
/* 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 <librsvg/rsvg.h>
+
+/* 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
- Re: SVG support(again) ?, (continued)
- Re: SVG support(again) ?, Richard Stallman, 2007/08/11
- Re: SVG support(again) ?, joakim, 2007/08/14
- Re: SVG support(again) ?, Richard Stallman, 2007/08/14
- Re: SVG support(again) ?, Mathias Dahl, 2007/08/15
- Re: SVG support(again) ?, joakim, 2007/08/16
- Re: SVG support(again) ?, Richard Stallman, 2007/08/16
- Re: SVG support(again) ?, joakim, 2007/08/18
- Re: SVG support(again) ?, Richard Stallman, 2007/08/18
- Re: SVG support(again) ?, joakim, 2007/08/19
- Re: SVG support(again) ?, Richard Stallman, 2007/08/19
- Re: SVG support(again) ?,
joakim <=
- Re: SVG support(again) ?, Richard Stallman, 2007/08/21
- Re: SVG support(again) ?, joakim, 2007/08/21
- Re: SVG support(again) ?, Glenn Morris, 2007/08/22
- Re: SVG support(again) ?, joakim, 2007/08/22
- svn icons in the toolbar (was: SVG support(again) ?), Leo, 2007/08/29
- Re: svn icons in the toolbar, Jan Djärv, 2007/08/30
- Re: svn icons in the toolbar, Leo, 2007/08/30
- Re: svn icons in the toolbar, Jan Djärv, 2007/08/31
- Re: svn icons in the toolbar, Benjamin Hawkes-Lewis, 2007/08/31
- Re: svn icons in the toolbar, Richard Stallman, 2007/08/30