* SVG and Emacs
@ 2004-09-20 1:02 Paul Pogonyshev
2004-09-20 15:17 ` Richard Stallman
0 siblings, 1 reply; 6+ messages in thread
From: Paul Pogonyshev @ 2004-09-20 1:02 UTC (permalink / raw)
There is an item in `etc/TODO' that says: ``Add support
for SVG (Scalable Vector Graphics) rendering to Emacs.''
Has anybody started on this? If not, I may be willing
to have a try, provided that `librsvg' usage is acceptable.
That library (basically) requires GTK+, libart, libxml and
Xft2. Doesn't mean that it cannot be used in Emacs
`--with-x', of course.
Paul
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: SVG and Emacs
2004-09-20 1:02 SVG and Emacs Paul Pogonyshev
@ 2004-09-20 15:17 ` Richard Stallman
2004-09-20 20:38 ` Paul Pogonyshev
0 siblings, 1 reply; 6+ messages in thread
From: Richard Stallman @ 2004-09-20 15:17 UTC (permalink / raw)
Cc: emacs-devel
Has anybody started on this? If not, I may be willing
to have a try, provided that `librsvg' usage is acceptable.
That library (basically) requires GTK+, libart, libxml and
Xft2.
It is rather a heavyweight solution. Is there no library
for SVG which doesn't need these things?
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: SVG and Emacs
2004-09-20 15:17 ` Richard Stallman
@ 2004-09-20 20:38 ` Paul Pogonyshev
2004-09-22 7:11 ` Richard Stallman
0 siblings, 1 reply; 6+ messages in thread
From: Paul Pogonyshev @ 2004-09-20 20:38 UTC (permalink / raw)
Cc: emacs-devel
> Has anybody started on this? If not, I may be willing
> to have a try, provided that `librsvg' usage is acceptable.
> That library (basically) requires GTK+, libart, libxml and
> Xft2.
>
> It is rather a heavyweight solution. Is there no library
> for SVG which doesn't need these things?
I only know about librsvg and ksvg (KDE SVG library, must be
much heavier).
Actually, librsvg doesn't use full GTK+, only gdk-pixbuf,
GLib and Pango. Maybe it could be made dynamically-loadable
(though I can't say I'm familiar with dynamic library loading).
Paul
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: SVG and Emacs
2004-09-20 20:38 ` Paul Pogonyshev
@ 2004-09-22 7:11 ` Richard Stallman
2004-09-25 20:31 ` Paul Pogonyshev
0 siblings, 1 reply; 6+ messages in thread
From: Richard Stallman @ 2004-09-22 7:11 UTC (permalink / raw)
Cc: emacs-devel
Actually, librsvg doesn't use full GTK+, only gdk-pixbuf,
GLib and Pango. Maybe it could be made dynamically-loadable
(though I can't say I'm familiar with dynamic library loading).
Maybe that is ok.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: SVG and Emacs
2004-09-22 7:11 ` Richard Stallman
@ 2004-09-25 20:31 ` Paul Pogonyshev
2004-09-26 8:27 ` Richard Stallman
0 siblings, 1 reply; 6+ messages in thread
From: Paul Pogonyshev @ 2004-09-25 20:31 UTC (permalink / raw)
Cc: emacs-devel
RMS wrote:
> Actually, librsvg doesn't use full GTK+, only gdk-pixbuf,
> GLib and Pango. Maybe it could be made dynamically-loadable
> (though I can't say I'm familiar with dynamic library loading).
>
> Maybe that is ok.
Here is the first shot. It is extremely non-portable, hackish and
ugly, but it works! :)
Do we want to continue in this direction? If yes, then I'm open for
suggestions, especially on how to improve `configure.in' and
`Makefile.in' bits. Portability is also a major issue. I only work
under GNU/Linux and I don't really know how portable `librsvg' is,
in the first place.
Also, do we want to make SVG rendering dynamically loadable
(optionally?) Actually, if we go on this, we can as well make all
the rest of image renderers load their libraries with dlopen().
From what I understood by looking at the code, the libraries are
already loaded dynamically under WinNT, so there must not be any
principal show-stoppers here.
Note that many ``1 ||'' in `image.c' are because I didn't run
Autoheader and so `HAVE_RSVG' didn't make its way to `config.h'.
Two side note on `configure.in':
* Many modules (i.e. image-rendering modules) that are built by
default are mentioned as `--with-xxx use -lxxx ...' in the help
output. It seems more logical to write
`--without-xxx don't use -lxxx ...'
* Maybe it is better to use AC_HELP_STRING()?
Paul
--- configure.in 04 May 2004 19:24:09 -0200 1.367
+++ configure.in 25 Sep 2004 16:16:10 -0200
@@ -109,10 +109,12 @@ AC_ARG_WITH(gif,
[ --with-gif use -lungif for displaying GIF images])
AC_ARG_WITH(png,
[ --with-png use -lpng for displaying PNG images])
+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])
@@ -1926,6 +1928,31 @@ AC_DEFUN([PKG_CHECK_MODULES], [
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
if test "$USE_X_TOOLKIT" != "none" && test "$USE_X_TOOLKIT" != "maybe"; then
@@ -3035,6 +3062,7 @@ echo " Does Emacs use -ljpeg?
echo " Does Emacs use -ltiff? ${HAVE_TIFF}"
echo " Does Emacs use -lungif? ${HAVE_GIF}"
echo " Does Emacs use -lpng? ${HAVE_PNG}"
+echo " Does Emacs use -lrsvg-2? ${HAVE_RSVG}"
echo " Does Emacs use X toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS}"
echo
--- lisp/image-file.el 01 Sep 2003 13:45:13 -0200 1.19
+++ lisp/image-file.el 25 Sep 2004 17:54:33 -0200
@@ -38,7 +38,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'.
--- lisp/image.el 21 Jun 2004 19:52:28 -0200 1.42
+++ lisp/image.el 25 Sep 2004 17:58:38 -0200
@@ -40,7 +40,8 @@
("\\`[\t\n\r ]*#define" . 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,
--- src/image.c 30 Jun 2004 11:11:36 -0200 1.16
+++ src/image.c 25 Sep 2004 18:16:31 -0200
@@ -7589,6 +7589,277 @@ gif_load (f, img)
#endif /* HAVE_GIF */
+
+/***********************************************************************
+ SVG
+ ***********************************************************************/
+
+#if 1 || 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 <librsvg/rsvg.h>
+
+/* 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;
+}
+
+
+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
+
+ 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) */
+
/***********************************************************************
@@ -7976,6 +8247,11 @@ of `image-library-alist', which see). *
return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
#endif
+#if 1 || 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);
@@ -8082,6 +8358,12 @@ To check whether it is really supported,
ADD_IMAGE_TYPE(Qpng);
#endif
+#if 1 || defined (HAVE_RSVG)
+ Qsvg = intern ("svg");
+ staticpro (&Qsvg);
+ ADD_IMAGE_TYPE(Qsvg);
+#endif
+
defsubr (&Sinit_image_library);
defsubr (&Sclear_image_cache);
defsubr (&Simage_size);
--- src/Makefile.in 10 Sep 2004 21:26:00 -0200 1.300
+++ src/Makefile.in 25 Sep 2004 16:25:50 -0200
@@ -280,7 +280,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}
+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}
.c.o:
$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $<
@@ -444,7 +444,7 @@ LIBXT=$(LIBW)
/* 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
+LIBX= $(LIBXMENU) $(X11_LDFLAGS) $(LIBXT) LIBTIFF LIBJPEG LIBPNG LIBGIF LIBXPM @RSVG_LIBS@ LIB_X11_LIB LIBX11_MACHINE LIBX11_SYSTEM
#else /* not HAVE_X11 */
LIBX= $(LIBXMENU) LD_SWITCH_X_SITE -lX10 LIBX10_MACHINE LIBX10_SYSTEM
#endif /* not HAVE_X11 */
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: SVG and Emacs
2004-09-25 20:31 ` Paul Pogonyshev
@ 2004-09-26 8:27 ` Richard Stallman
0 siblings, 0 replies; 6+ messages in thread
From: Richard Stallman @ 2004-09-26 8:27 UTC (permalink / raw)
Cc: emacs-devel
Here is the first shot. It is extremely non-portable, hackish and
ugly, but it works! :)
I don't have time to read the code, but I am please that the
amount of new code is so small.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2004-09-26 8:27 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-09-20 1:02 SVG and Emacs Paul Pogonyshev
2004-09-20 15:17 ` Richard Stallman
2004-09-20 20:38 ` Paul Pogonyshev
2004-09-22 7:11 ` Richard Stallman
2004-09-25 20:31 ` Paul Pogonyshev
2004-09-26 8:27 ` Richard Stallman
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.