How to convert SVG paths to Lilypond paths

From About PCs Wiki
Jump to navigation Jump to search

Introduction[edit | hide | hide all]

Lilypond is not only a music engraving program, but has amazing drawing capabilities. The text markup command has a graphic section. It is possible to embed EPS and Postscript files.

The feature I am talking here is the path command which allows to define your own graph. There are seven commands available moveto, rmoveto, lineto, rlineto, curveto, rcurveto, and closepath. The Lilypond code snippet repository shows some examples featuring the path command.

What are the advantages of path compared to embed an EPS file? The color can be adapted, obiously you can only use one color per path.

I use Lilypond for drawing title sheets with ornaments and want to change the color simply.

EPS paths and Lilypond[edit | hide]

When looking inside an EPS file we see similarities to Lilypond path

comparision EPS with Lilypond path
EPS path Lilypond path
	92 1184 moveto
	 96 1566 131 1873 197 2105 curveto
	 263 2337 368.667 2510.67 514 2626 curveto
	 675.333 2748.67 881.667 2810 1133 2810 curveto
	 1326.33 2810 1477.67 2777.33 1587 2712 curveto
	 1688.33 2656 1739 2591.67 1739 2519 curveto
	 1739 2471 1730.67 2423.33 1714 2376 curveto
	 2009.33 2300.67 2157 1962 2157 1360 curveto
	 2157 1040 2124.33 754 2059 502 curveto
	 1993.67 250.667 1852.67 88.6667 1636 16 curveto
	 1561.33 -11.3333 1478 -25 1386 -25 curveto
	 1370.67 -25 1351 -24 1327 -22 curveto
	 1303 -20 1275 -16.6667 1243 -12 curveto
	 1179.67 -4 1129.33 0 1092 0 curveto
	 1055.33 0 1006 -4 944 -12 curveto
	 913.333 -16.6667 886.333 -20 863 -22 curveto
	 839.667 -24 820.333 -25 805 -25 curveto
	 619.667 -25 474 38.6667 368 166 curveto
	 261.333 294.667 188.667 449 150 629 curveto
	 111.333 808.333 92 993.333 92 1184 curveto
	closepath
(moveto 92 1184 )
(curveto 96 1566 131 1873 197 2105 )
(curveto 263 2337 368.667 2510.67 514 2626 )
(curveto 675.333 2748.67 881.667 2810 1133 2810 )
(curveto 1326.33 2810 1477.67 2777.33 1587 2712 )
(curveto 1688.33 2656 1739 2591.67 1739 2519 )
(curveto 1739 2471 1730.67 2423.33 1714 2376 )
(curveto 2009.33 2300.67 2157 1962 2157 1360 )
(curveto 2157 1040 2124.33 754 2059 502 )
(curveto 1993.67 250.667 1852.67 88.6667 1636 16 )
(curveto 1561.33 -11.3333 1478 -25 1386 -25 )
(curveto 1370.67 -25 1351 -24 1327 -22 )
(curveto 1303 -20 1275 -16.6667 1243 -12 )
(curveto 1179.67 -4 1129.33 0 1092 0 )
(curveto 1055.33 0 1006 -4 944 -12 )
(curveto 913.333 -16.6667 886.333 -20 863 -22 )
(curveto 839.667 -24 820.333 -25 805 -25 )
(curveto 619.667 -25 474 38.6667 368 166 )
(curveto 261.333 294.667 188.667 449 150 629 )
(curveto 111.333 808.333 92 993.333 92 1184 )
(closepath)

EPS looks a lot like a Lilypond path, and I suppose that the programers of Lilypond use EPS as template for the path command.

The conversion is quite simple using Lua and some regex magic

function p.abs(frame)
	local a = frame.args              -- direkt per #invoke: ├╝bergeben
	local b = frame:getParent().args  -- an die Vorlage ├╝bergebene Parameter
	-- {{{}}}#invoke:Eps|lily|pfad=
	-- returnd Lilypond path definition as single path from eps
	-- pfad or unnamed parameter 1: eps definition
	-- pfadname or parameter 2:     name of Lilypond path, default = svgpath
	
	local pfad = trim(b["pfad"] or a["pfad"] or b[1] or a[1] or '')
	if pfad == '' then return "<div class=\"blue-gradient fett noclick lily\" style=\"font-size: 1.4em; padding: 10px\">Pfad fehlt</div>" end
	
	local epspat = "%s*([%d%.%- ]*)([%l]+)"
	local numpat = "[%d%.%-]+"
	local lilypath = ""
	local koord, kurven = {}, {}
	
	for zahlen, curve in pfad:gmatch(epspat) do
		if curve:match("eto") or curve:match("closepath") then
			table.insert(koord,zahlen)
			table.insert(kurven,curve)
		end
	end
	
	for i = 1, #koord do
		lilypath = lilypath .. '\n(' .. kurven[i] .. ' ' .. koord[i] .. ')'
	end

	local wikipath = '\n<tabber>\n' ..
				'Lilypond path definition=<syntaxhighlight lang=\"scheme\" style=\"display: inline-block\">' ..
				lilypath .. "</syntaxhighlight>\n|-|\n" .. 
				'Lilypond path definition oneclick=\n' ..
				'<syntaxhighlight lang=\"scheme\" style=\"display: inline-block\" class=\"oneclick\">' ..
				lilypath .. '</syntaxhighlight>\n</tabber>' 

	return wikipath

end

Update: Only few programs do produce EPS paths like this, so you have to try harder

SVG paths[edit | hide]

SVG paths can contain a lot more elements than Lilypond paths.

The simple solution is to find a program that converts SVG to EPS, for fonts FontForge can do that, for SVG use Inkscape

If the EPS conversion looks a lot different, you have to do it a more complicated way.

Example[edit | hide]

#(define
  zzero
  '(
     (moveto 0 0)
     (rcurveto 4 382 39 689 105 921)
     (rcurveto 66 232 171.667 405.67 317 521)
     (rcurveto 161.333 122.67 367.667 184 619 184)
     (rcurveto 193.33 0 344.67 -32.67 454 -98)
     (rcurveto 101.33 -56 152 -120.33 152 -193)
     (rcurveto 0 -48 -8.33 -95.67 -25 -143)
     (rcurveto 295.33 -75.33 443 -414 443 -1016)
     (rcurveto 0 -320 -32.67 -606 -98 -858)
     (rcurveto -65.33 -251.333 -206.33 -413.3333 -423 -486)
     (rcurveto -74.67 -27.3333 -158 -41 -250 -41)
     (rcurveto -15.33 0 -35 1 -59 3)
     (rcurveto -24 2 -52 5.3333 -84 10)
     (rcurveto -63.33 8 -113.67 12 -151 12)
     (rcurveto -36.67 0 -86 -4 -148 -12)
     (rcurveto -30.667 -4.6667 -57.667 -8 -81 -10)
     (rcurveto -23.333 -2 -42.667 -3 -58 -3)
     (rcurveto -185.333 0 -331 63.6667 -437 191)
     (rcurveto -106.667 128.667 -179.333 283 -218 463)
     (rcurveto -38.667 179.333 -58 364.333 -58 555)
     (closepath)
     (rmoveto 410 368)
     (rcurveto 0 -310 46 -550.33 138 -721)
     (rcurveto 92 -169.333 250.667 -256.667 476 -262)
     (rcurveto 251.33 0 427.67 91.667 529 275)
     (rcurveto 100.67 182.67 151 410.67 151 684)
     (rcurveto 0 206.67 -24.67 369 -74 487)
     (rcurveto -27.33 79.33 -66.67 119 -118 119)
     (rcurveto -18.67 0 -35.33 -2.33 -50 -7)
     (rcurveto -14.67 -4 -40 -12 -76 -24)
     (rcurveto -17.33 -6 -31.5 -10.83 -42.5 -14.5)
     (rcurveto -11 -3.67 -19.17 -6.17 -24.5 -7.5)
     (rcurveto -42.67 8 -74 21 -94 39)
     (rcurveto -20 18.67 -36.33 48 -49 88)
     (rcurveto 7.33 26 31.33 63.33 72 112)
     (rcurveto 42 50 63 93 63 129)
     (rcurveto 0 56 -29 99.67 -87 131)
     (rcurveto -57.33 30.67 -129.33 46 -216 46)
     (rcurveto -169.333 0 -297.333 -56.33 -384 -169)
     (rcurveto -87.333 -112 -143.333 -242.33 -168 -391)
     (rcurveto -12.667 -74.67 -22.667 -154.5 -30 -239.5)
     (rcurveto -7.333 -85 -12.667 -176.5 -16 -274.5)
     (closepath)
     ))

\markup \with-color #(rgb-color (/ 150 255) (/ 123 255) (/ 31 255))
\scale #'(.02 . .02)
\override #'(filled . #t) \path #0 #zzero

#(define
  zzero
  '(
     (moveto 0 0)
     (rcurveto 4 382 39 689 105 921)
     (rcurveto 66 232 171.667 405.67 317 521)
     (rcurveto 161.333 122.67 367.667 184 619 184)
     (rcurveto 193.33 0 344.67 -32.67 454 -98)
     (rcurveto 101.33 -56 152 -120.33 152 -193)
     (rcurveto 0 -48 -8.33 -95.67 -25 -143)
     (rcurveto 295.33 -75.33 443 -414 443 -1016)
     (rcurveto 0 -320 -32.67 -606 -98 -858)
     (rcurveto -65.33 -251.333 -206.33 -413.3333 -423 -486)
     (rcurveto -74.67 -27.3333 -158 -41 -250 -41)
     (rcurveto -15.33 0 -35 1 -59 3)
     (rcurveto -24 2 -52 5.3333 -84 10)
     (rcurveto -63.33 8 -113.67 12 -151 12)
     (rcurveto -36.67 0 -86 -4 -148 -12)
     (rcurveto -30.667 -4.6667 -57.667 -8 -81 -10)
     (rcurveto -23.333 -2 -42.667 -3 -58 -3)
     (rcurveto -185.333 0 -331 63.6667 -437 191)
     (rcurveto -106.667 128.667 -179.333 283 -218 463)
     (rcurveto -38.667 179.333 -58 364.333 -58 555)
     (closepath)
     (rmoveto 410 368)
     (rcurveto 0 -310 46 -550.33 138 -721)
     (rcurveto 92 -169.333 250.667 -256.667 476 -262)
     (rcurveto 251.33 0 427.67 91.667 529 275)
     (rcurveto 100.67 182.67 151 410.67 151 684)
     (rcurveto 0 206.67 -24.67 369 -74 487)
     (rcurveto -27.33 79.33 -66.67 119 -118 119)
     (rcurveto -18.67 0 -35.33 -2.33 -50 -7)
     (rcurveto -14.67 -4 -40 -12 -76 -24)
     (rcurveto -17.33 -6 -31.5 -10.83 -42.5 -14.5)
     (rcurveto -11 -3.67 -19.17 -6.17 -24.5 -7.5)
     (rcurveto -42.67 8 -74 21 -94 39)
     (rcurveto -20 18.67 -36.33 48 -49 88)
     (rcurveto 7.33 26 31.33 63.33 72 112)
     (rcurveto 42 50 63 93 63 129)
     (rcurveto 0 56 -29 99.67 -87 131)
     (rcurveto -57.33 30.67 -129.33 46 -216 46)
     (rcurveto -169.333 0 -297.333 -56.33 -384 -169)
     (rcurveto -87.333 -112 -143.333 -242.33 -168 -391)
     (rcurveto -12.667 -74.67 -22.667 -154.5 -30 -239.5)
     (rcurveto -7.333 -85 -12.667 -176.5 -16 -274.5)
     (closepath)
     ))