4

Looking for a tool to programmatically generate SVG images, I found that Emacs 26 can do it out of the box!

Example adapted from the Elisp reference manual:

(require 'svg)
(let ((svg (svg-create 400 400 :stroke-width 10)))
  (svg-gradient svg "gradient1" 'linear '((0 . "red") (100 . "blue")))
  (svg-circle svg 200 200 100 :gradient "gradient1" :stroke-color "green")
  svg)

Now how do I save that to an SVG file?

I’m using Emacs 26.1 in the Termux terminal emulator on my phone, so no graphics.

Drew
  • 77,472
  • 10
  • 114
  • 243
feklee
  • 1,079
  • 5
  • 17
  • 2
    svg seems to contain XML structure stored as a list. It seems you'd need to just serialize it back to XML, and you'd get a svg string you could save to a file. I'm looking for a function that can do such serialization, and surprisingly, libxml has only parsing functions. –  Jul 28 '18 at 16:10

2 Answers2

3

Thought I shouldn’t be lazy and found a way by digging around and reading docs. Key is the svg-print function which serializes the svg structure:

(require 'svg)
(let ((svg (svg-create 400 400 :stroke-width 10)))
  (svg-gradient svg "gradient1" 'linear '((0 . "red") (100 . "blue")))
  (svg-circle svg 200 200 100 :gradient "gradient1" :stroke-color "green")
  (with-temp-file "circle.svg"
    (set-buffer-multibyte nil)
    (svg-print svg)))
feklee
  • 1,079
  • 5
  • 17
3

And if, like me, you're trying to do the same in org-mode, with-temp-buffer in combination with buffer-string does the trick:

#+begin_src emacs-lisp :file test.svg
    (let ((svg (svg-create 400 400 :stroke-width 10)))
      (svg-gradient svg "gradient1" 'linear '((0 . "red") (100 . "blue")))
      (svg-circle svg 200 200 100 :gradient "gradient1" :stroke-color "green")
      (with-temp-buffer
        (svg-print svg)
        (buffer-string)))
#+end_src