SVG support(again) ?

View: New views
20 Messages — Rating Filter:   Alert me  
< Prev | 1 - 2 - 3 - 4 - 5 - 6 | Next >

SVG support(again) ?

by Joakim Verona :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

There was a patch for SVG support in Emacs in 2004.
This patch seems to no longer apply.

Has anyone adopted it for the current tree? If so, coculd it be
applied?

--
Joakim Verona



_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Joakim Verona :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

joakim@... writes:

> There was a patch for SVG support in Emacs in 2004.
> This patch seems to no longer apply.

I've adapted the SVG patch by Paul Pogonyshev for current emacs CVS.
All I did was find the right place to insert the hunks, since the
emacs source has changed a lot since the original patch.

I tried it briefly on a Fedora 7 box. It seems to work nicely.

What must be done in order for this patch to be applied?

The only odd thing I can see is three lines like:

#if 1 || defined (HAVE_RSVG)

that ought to be the same as:

#if defined (HAVE_RSVG)

which should be ok on any plattform, since HAVE_RSVG will be defined
only if you have librsvg2. I did try the configure script generated by
autoconf once withouth the lib and once with.

I tried making a SVG picture with Inkscape, viewing it in emacs using
image-dired, and then editing it a bit with nxml mode, and it seemed
to work nicely.


? emacs_svg.patch
Index: configure.in
===================================================================
RCS file: /sources/emacs/emacs/configure.in,v
retrieving revision 1.459
diff -r1.459 configure.in
112a113,114
> AC_ARG_WITH(rsvg,
> [  --with-rsvg             use -lrsvg-2 for displaying SVG images])
116c118
< [  --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])
2124a2127,2152

> ### 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
>
>
3364a3393
> echo "  Does Emacs use -lrsvg-2?                                ${HAVE_RSVG}"
Index: lisp/image-file.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/image-file.el,v
retrieving revision 1.29
diff -r1.29 image-file.el
42c42
<   '("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")
Index: lisp/image.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/image.el,v
retrieving revision 1.72
diff -r1.72 image.el
46c46,47
<     ("\\`\xff\xd8" . (image-jpeg-p . jpeg)))
---
>     ("\\`\xff\xd8" . (image-jpeg-p . jpeg))
>     ("\\`<\\?xml " . svg))
Index: src/Makefile.in
===================================================================
RCS file: /sources/emacs/emacs/src/Makefile.in,v
retrieving revision 1.346
diff -r1.346 Makefile.in
284c284
< 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}
453c453
< 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)
Index: src/image.c
===================================================================
RCS file: /sources/emacs/emacs/src/image.c,v
retrieving revision 1.77
diff -r1.77 image.c
8201a8202,8474

>  
> /***********************************************************************
> 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) */
>
>
>
8593a8867,8871
> #if 1 || defined (HAVE_RSVG)
>   if (EQ (type, Qsvg))
>     return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries);
> #endif
>  
8735a9014,9020
> #if 1 || defined (HAVE_RSVG)
>   Qsvg = intern ("svg");
>   staticpro (&Qsvg);
>   ADD_IMAGE_TYPE(Qsvg);
> #endif
>
>  



>
> Has anyone adopted it for the current tree? If so, coculd it be
> applied?
>
> --
> Joakim Verona

--
Joakim Verona

_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by David Kastrup :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

joakim@... writes:

> joakim@... writes:
>
>> There was a patch for SVG support in Emacs in 2004.
>> This patch seems to no longer apply.
>
> I've adapted the SVG patch by Paul Pogonyshev for current emacs CVS.
> All I did was find the right place to insert the hunks, since the
> emacs source has changed a lot since the original patch.
>
> I tried it briefly on a Fedora 7 box. It seems to work nicely.
>
> What must be done in order for this patch to be applied?
>
> The only odd thing I can see is three lines like:
>
> #if 1 || defined (HAVE_RSVG)
>
> that ought to be the same as:
>
> #if defined (HAVE_RSVG)

No, it is the same as
#if 1
period.

--
David Kastrup, Kriemhildstr. 15, 44793 Bochum


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Jason Rumney-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

David Kastrup wrote:

>> The only odd thing I can see is three lines like:
>>
>> #if 1 || defined (HAVE_RSVG)
>>
>> that ought to be the same as:
>>
>> #if defined (HAVE_RSVG)
>>    
>
> No, it is the same as
> #if 1
> period.
>  

Going back and looking at the original discussion from Sept 2004, the 1
|| is there because he hadn't bothered with the configury stuff that
would have made the HAVE_RSVG work.





_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Joakim Verona :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

David Kastrup <dak@...> writes:

> joakim@... writes:
>
>> joakim@... writes:
>>
>>> There was a patch for SVG support in Emacs in 2004.
>>> This patch seems to no longer apply.
>>
>> I've adapted the SVG patch by Paul Pogonyshev for current emacs CVS.
>> All I did was find the right place to insert the hunks, since the
>> emacs source has changed a lot since the original patch.
>>
>> I tried it briefly on a Fedora 7 box. It seems to work nicely.
>>
>> What must be done in order for this patch to be applied?
>>
>> The only odd thing I can see is three lines like:
>>
>> #if 1 || defined (HAVE_RSVG)
>>
>> that ought to be the same as:
>>
>> #if defined (HAVE_RSVG)
>
> No, it is the same as
> #if 1
> period.

Thanks! I suppose I should get more sleep.

#if defined (HAVE_RSVG)

seems to work though. Am I missing something else?

>
> --
> David Kastrup, Kriemhildstr. 15, 44793 Bochum

--
Joakim Verona


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Joakim Verona :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Jason Rumney <jasonr@...> writes:

> Going back and looking at the original discussion from Sept 2004, the 1
> || is there because he hadn't bothered with the configury stuff that
> would have made the HAVE_RSVG work.

I think the configury stuff does work, but maybe it didnt originaly.

This line in configure.in:

echo "  Does Emacs use -lrsvg-2?                                ${HAVE_RSVG}"

corectly prints "yes" if librsvg2-devel is installed, but "no" if it
isnt. The rest of the code gets to be correct if "#if 1 ..." is changed
to "if defined(HAVE_RSVG)" in  the patch.



--
Joakim Verona


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Richard Stallman :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

    I've adapted the SVG patch by Paul Pogonyshev for current emacs CVS.
    All I did was find the right place to insert the hunks, since the
    emacs source has changed a lot since the original patch.

    I tried it briefly on a Fedora 7 box. It seems to work nicely.

    What must be done in order for this patch to be applied?

We have the legal papers.  The code needs more comments.  We also need
the entry for etc/NEWS, and it would be nice to write text for the
manual now.  (I will polish it up once it is installed.)


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Joakim Verona :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Richard Stallman <rms@...> writes:

>     I've adapted the SVG patch by Paul Pogonyshev for current emacs CVS.
>     All I did was find the right place to insert the hunks, since the
>     emacs source has changed a lot since the original patch.
>
>     I tried it briefly on a Fedora 7 box. It seems to work nicely.
>
>     What must be done in order for this patch to be applied?
>
> We have the legal papers.  The code needs more comments.  We also need
> the entry for etc/NEWS, and it would be nice to write text for the
> manual now.  (I will polish it up once it is installed.)

- Is this text for NEWS ok?

** Support for SVG images

Emacs now supports the SVG image format through librsvg2.


- There appears to be only generic text in the emacs manual for image
  viewing, valid for all image types. Viewing SVG images is no
  different from viewing JPG images, so I think the manual doesnt need
  any particular updates for this patch.

- I looked through the code briefly, and it didnt seem too bad on the
  commenting. Was it anything in particular you thought needed clarification?
 
--
Joakim Verona


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Richard Stallman :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

    - 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.


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Mathias Dahl-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

>     - 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.

This is why I like M-x checkdoc RET so much :)


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Joakim Verona :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Richard Stallman <rms@...> 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 <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;
}

/* 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


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Richard Stallman :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

    /* Structure describing the image type `svg'.  */

    static struct image_type svg_type =
    {
      &Qsvg,
      svg_image_p,
      svg_load,
      x_clear_image,
      NULL
    };

How about adding another comment for each field explaining what
the field means and why this particular value is used.

    /* DEF_IMGLIB_FN() here? */

I don't understand that comment -- if you do, could you make
it less terse, and clear?

    /* 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
    */

That is terse and cryptic.  Could you rewrite it to be clear
and format it the way we like to do?

The code of svg_load_image needs more comments explaining what the
parts of the code do.


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Joakim Verona :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Richard Stallman <rms@...> writes:

>     /* Structure describing the image type `svg'.  */
>
>     static struct image_type svg_type =
>     {
>       &Qsvg,
>       svg_image_p,
>       svg_load,
>       x_clear_image,
>       NULL
>     };
>
> How about adding another comment for each field explaining what
> the field means and why this particular value is used.
>
>     /* DEF_IMGLIB_FN() here? */
>
> I don't understand that comment -- if you do, could you make
> it less terse, and clear?
>
>     /* 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
>     */
>
> That is terse and cryptic.  Could you rewrite it to be clear
> and format it the way we like to do?
>
> The code of svg_load_image needs more comments explaining what the
> parts of the code do.

Here is a new try. I believe this is quite readable now.
Note that some of the difficulty in understanding this code comes from
reading it in isolation from the other code im image.c. I tried
adding some helpful pointers to other emacs code.


/***********************************************************************
                                 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 =
{
  &Qsvg, /* an identifier showing that this is an image structure for the SVG format*/
  svg_image_p, /* handle to a function that can be used to identify a svg file*/
  svg_load, /* handle to function used to load a svg file*/
  x_clear_image,/* handle to function to free sresources for SVG*/
  NULL /* an internal field to link to the next image type in a list of image types, will be filled in when registering the format*/
};


/* 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>

/* DEF_IMGLIB_FN() here in the future.
this macro is used to handle loading of dynamic link library functions for various OS:es.
currently only librsvg2 is supportedd, 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 wil 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;
      }

      contents = slurp_file (SDATA (file), &size); /* read the entire file into memory*/
      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); /* if the file was slurped into memory properly, parse it*/
      xfree (contents);
      UNGCPRO;
    }
  else/*its not a file, its a lisp object*/
    {
      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 (); /*glib function that must be called prior to using gnome type library functions*/
  rsvg_handle = fn_rsvg_handle_new ();/* make a handle to a new rsvg object*/

  fn_rsvg_handle_write (rsvg_handle, contents, size, &error);/*parse "contents" and fill in the rsvg_handle*/
  if (error)
    goto rsvg_error;

  fn_rsvg_handle_close (rsvg_handle, &error);/*the parsing is complete, rsvg_handle is ready to use*/
  if (error)
    goto rsvg_error;

  pixbuf = fn_rsvg_handle_get_pixbuf (rsvg_handle);/* we can now get a valid pixel buffer from the svg file, if all went ok*/
  eassert (pixbuf);

  /* extract some meta data from he 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 ();

#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. */
  image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
  g_error_free (error);
  return 0;
}

#endif /* defined (HAVE_RSVG) */



--
Joakim Verona


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Richard Stallman :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

You're getting closer.  There are enough comments now,
but they need to be formatted cleanly and consistently with the
rest of Emacs.

    /* DEF_IMGLIB_FN() here in the future.

Do you mean

    /* TO DO: use DEF_IMGLIB_FN here.

It is vital to use words like "TO DO:" and "use",
because following such patterns makes the meaning clear.

(In GNU we don't write `()' after a function name.)

Aside from that, it will be clean if you fill the comment lines
to 70 character width.

Also, please use two spaces at the end of a sentence,
and please put a period and two spaces at the end of every comment
that contents sentences.

    /* Load SVG image IMG for use on frame F.  Value is non-zero if
       successful. this function wil go into the svg_type structure, and
       the prototype thus needs to be compatible with that structure */

should be

    /* 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, so it needs to be compatible with that structure.  */


          contents = slurp_file (SDATA (file), &size); /* read the entire file into memory*/

That style makes lines wide and hard to read, so please put the comment
on a separate line.  It should start with a capital letter, and end
with a period and two spaces.

          /* Read the entire file into memory.  */
          contents = slurp_file (SDATA (file), &size);


    /* 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
    */

This should explain each of the arguments by name.
Please also start it with a capital letter, and end it with a period,
and avoid lines that are too long.


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Joakim Verona :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Richard Stallman <rms@...> writes:

> You're getting closer.  There are enough comments now,
> but they need to be formatted cleanly and consistently with the
> rest of Emacs.
>
>     /* DEF_IMGLIB_FN() here in the future.
>
> Do you mean
>
>     /* TO DO: use DEF_IMGLIB_FN here.
>
> It is vital to use words like "TO DO:" and "use",
> because following such patterns makes the meaning clear.
>
> (In GNU we don't write `()' after a function name.)
>
> Aside from that, it will be clean if you fill the comment lines
> to 70 character width.
>
> Also, please use two spaces at the end of a sentence,
> and please put a period and two spaces at the end of every comment
> that contents sentences.
>
>     /* Load SVG image IMG for use on frame F.  Value is non-zero if
>        successful. this function wil go into the svg_type structure, and
>        the prototype thus needs to be compatible with that structure */
>
> should be
>
>     /* 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, so it needs to be compatible with that structure.  */
>
>
>  contents = slurp_file (SDATA (file), &size); /* read the entire file into memory*/
>
> That style makes lines wide and hard to read, so please put the comment
> on a separate line.  It should start with a capital letter, and end
> with a period and two spaces.
>
>           /* Read the entire file into memory.  */
>  contents = slurp_file (SDATA (file), &size);
>
>
>     /* 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
>     */
>
> This should explain each of the arguments by name.
> Please also start it with a capital letter, and end it with a period,
> and avoid lines that are too long.

Ok, this is the next iteration. Thanks for your patience!


/***********************************************************************
                                 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) */

--
Joakim Verona


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Richard Stallman :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

The code is now ready for installation.  Thank you.
To install it requires a change log entry, and a NEWS entry.


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Joakim Verona :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Richard Stallman <rms@...> 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 @@ 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 <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

_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Richard Stallman :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

    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.

Can you please write the change log entry for it?
It should reflect the authorship, both yours and his.


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Joakim Verona :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Richard Stallman <rms@...> writes:

>     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.
>
> Can you please write the change log entry for it?
> It should reflect the authorship, both yours and his.

Ok, heres my attempt:

2007-08-21  Paul Pogonyshev  <pogonyshev@...>

        * configure.in, image-file.el, image.el,
        * Makefile.in, image.c: Support the SVG image file
        format through librsvg2. Some additional code somments
        where written by Joakim Verona <joakim@...>.

--
Joakim Verona


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel

Re: SVG support(again) ?

by Glenn Morris-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Thanks for this, I installed it. Let me know if I missed anything.


_______________________________________________
Emacs-devel mailing list
Emacs-devel@...
http://lists.gnu.org/mailman/listinfo/emacs-devel
< Prev | 1 - 2 - 3 - 4 - 5 - 6 | Next >