1 ;;;; sodipodi.scm -- implement Scheme output routines for PostScript
3 ;;;; source file of the GNU LilyPond music typesetter
5 ;;;; (c) 2002 Jan Nieuwenhuizen <janneke@gnu.org>
9 ;;;; * Get mftrace 1.0.12 or newer
11 ;;;; * Get sodipodi-0.28 or newer
13 ;;;; * Link/copy mf/out/private-fonts to ~/.sodipodi/private-fonts
15 ;;;; http://www.w3.org/TR/SVG11/paths.html
18 (debug-enable 'backtrace)
21 (define-module (scm sodipodi))
22 (define this-module (current-module))
31 ;;; Lily output interface --- cleanup and docme
33 ;;; Bare minimum interface for \score { \notes c } }
36 ;;; xx-output-expression
41 ;;; and should intercept:
57 ;;(define-public (sodipodi-output-expression expr port)
58 ;; (display (eval expr this-module) port))
60 (define-public (sodipodi-output-expression expr port)
61 (display (dispatch expr) port))
64 (define (dispatch expr)
65 (let ((keyword (car expr)))
67 ((eq? keyword 'some-func) "")
68 ;;((eq? keyword 'placebox) (dispatch (cadddr expr)))
69 ;;((eq? keyword 'fontify) (dispatch (caddr expr)))
71 (if (module-defined? this-module keyword)
72 (apply (eval keyword this-module) (cdr expr))
75 (string-append "undefined: " (symbol->string keyword) "\n"))
81 (define output-scale 1)
83 (define line-thickness 0.1)
84 (define half-lt (/ line-thickness 2))
89 ((equal? (ly:unit) "mm") (/ 72.0 25.4))
90 ((equal? (ly:unit) "pt") (/ 72.0 72.27))
91 (else (error "unknown unit" (ly:unit)))))
93 ;; alist containing fontname -> fontcommand assoc (both strings)
94 ;;(define font-name-alist '())
99 (define (tagify tag string . attribute-alist)
102 (apply string-append (map (lambda (x) (string-append
104 (symbol->string (car x))
110 string "\n</" tag ">\n"))
113 (define (ascii->string i) (make-string 1 (integer->char i)))
114 (define (ascii->upm-string i)
117 (u2 (+ #x80 (quotient i+1 #x40)))
118 (u3 (+ #x80 (modulo i+1 #x40))))
123 (define (control->list c)
124 (list (car c) (cdr c)))
126 (define (control->string c)
128 (number->string (car c)) ","
130 (number->string (* -1 (cdr c))) " "))
132 (define (control-flip-y c)
133 (cons (car c) (* -1 (cdr c))))
135 (define (numbers->string l)
137 (number->string (car l))
140 (string-append "," (numbers->string (cdr l))))))
142 (define (svg-bezier l close)
143 (let* ((c0 (car (list-tail l 3)))
144 (c123 (list-head l 3)))
146 (if (not close) "M " "L ")
148 "C " (apply string-append (map control->string c123))
149 (if (not close) "" (string-append
150 "L " (control->string close))))));; " Z")))))
153 "<?xml version='1.0' standalone='no'?>
154 <!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 20010904//EN'
155 'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'
158 xmlns:xlink CDATA #FIXED 'http://www.w3.org/1999/xlink'>
167 sodipodi:version='0.26'
168 xmlns='http://www.w3.org/2000/svg'
169 xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'
170 xmlns:xlink='http://www.w3.org/1999/xlink'
173 sodipodi:docbase='/tmp/'
174 sodipodi:docname='/tmp/x'>
179 <g transform='translate(10,10) scale (1.0)'>
184 ;; Interface functions
189 (define (beam width slope thick)
192 (z (sqrt (+ (sqr x) (sqr y)))))
195 '(style . "fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;")
196 `(x . ,(number->string half-lt))
197 `(y . ,(number->string (- half-lt (/ thick 2))))
198 `(width . ,(number->string width))
199 `(height . ,(number->string thick))
200 `(ry . ,(number->string line-thickness))
201 `(transform . ,(format #f "matrix(~f,~f,0,1,0,0) scale (~f,~f)"
204 output-scale output-scale)))))
206 ;; TODO: bezier-ending, see ps.scm
207 (define (bezier-bow urg-l thick)
209 (define (bezier-ending z0 z1 z2)
216 (let ((r (/ (sqrt (+ (* (- x1 x2) (- x1 x2))
217 (* (- y1 y2) (- y1 y2)))) 2)))
220 `(cx . ,(number->string (* output-scale x0)))
221 `(cy . ,(number->string (* output-scale (- 0 y0))))
222 `(r . ,(number->string (* output-scale r)))))))
224 (let ((l (eval urg-l this-module)))
226 (bezier-sandwich l thick)
227 (bezier-ending (list-ref l 3) (list-ref l 0) (list-ref l 5))
228 (bezier-ending (list-ref l 7) (list-ref l 0) (list-ref l 5)))))
230 (define (bezier-sandwich l thick)
231 (let* (;;(l (eval urg-l this-module))
232 (first (list-tail l 4))
233 (first-c0 (car (list-tail first 3)))
234 (second (list-head l 4)))
236 `(stroke . "#000000")
237 `(stroke-width . ,(number->string line-thickness))
238 `(transform . ,(format #f "scale (~f,~f)"
239 output-scale output-scale))
240 `(d . ,(string-append (svg-bezier first #f)
241 (svg-bezier second first-c0))))))
245 ;;(tagify "tspan" (format #f "à~2,'0x;" i))
246 (tagify "tspan" (ascii->upm-string i))
248 (format #t "can't display char: ~x\n" i)
253 (string-append "<!-- " s " -->\n"))
255 (define (define-fonts internal-external-name-mag-pairs)
256 (comment (format #f "Fonts used: ~S" internal-external-name-mag-pairs)))
261 (define (filledbox breapth width depth height)
262 (roundfilledbox breapth width depth height line-thickness))
265 "fill:black;stroke:none;font-style:normal;font-weight:normal;text-anchor:start;writing-mode:lr;")
270 ("cmr8" . ,(string-append
272 "font-family:cmr;font-size:8;"))
273 ("feta13" . ,(string-append
275 "font-family:LilyPond-Feta;font-size:13;"))
276 ("feta-nummer10" . ,(string-append
278 "font-family:LilyPond-Feta-nummer;font-size:10;"))
279 ("feta20" . ,(string-append
281 "font-family:LilyPond-Feta;font-size:20;"))
282 ("parmesan20" . ,(string-append
284 "font-family:LilyPond-Parmesan;font-size:20;"))))
286 (define (get-font name-mag-pair)
287 ;; name-mag-pair: (quote ("feta20" . 0.569055118110236))"feta20"(quote ("feta20" . 0.569055118110236))
288 (let ((f (assoc (caadr name-mag-pair) font-alist)))
292 (format #t "font not found: ~s\n" (caadr name-mag-pair))
293 (cdr (assoc "feta20" font-alist))))))
295 (define (fontify name-mag-pair expr)
297 (tagify "text" (dispatch expr) (cons 'style (get-font name-mag-pair)))))
300 (comment "header-end"))
302 (define (header creator generate)
310 (define (lily-def key val)
311 (if (equal? key "lilypondpaperoutputscale")
313 ;; If we just use transform scale (output-scale),
314 ;; all fonts come out scaled too (ie, much too big)
315 ;; So, we manually scale all other stuff.
316 (set! output-scale (* scale-to-unit (string->number val))))
323 (define (placebox x y expr)
324 (tagify "g" (dispatch expr)
329 (number->string (* output-scale x))
331 (number->string (- 0 (* output-scale y)))
334 (define (roundfilledbox breapth width depth height blot-diameter)
337 '(style . "fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;")
338 `(x . ,(number->string (* output-scale (- 0 breapth))))
339 `(y . ,(number->string (* output-scale (- 0 height))))
340 `(width . ,(number->string (* output-scale (+ breapth width))))
341 `(height . ,(number->string (* output-scale (+ depth height))))
342 ;;`(ry . ,(number->string (* output-scale half-lt)))
343 `(ry . ,(number->string blot-diameter))))
347 ;; TODO: use height, set scaling?
348 (define (start-system width height)
350 ;;"<g transform='translate(50,-250)'>
351 (set! system-y (+ system-y height))
352 ;;(format #f "<g transform='translate(0,~1,'~f)'>" y)))
355 (comment "start-system")
356 (format #f "<g transform='translate(0.0,~f)'>\n" (* output-scale y)))))
358 (define (stop-system)
361 (comment "stop-system")
364 (define stop-last-system stop-system)
367 ;; to unicode or not?
371 (apply string-appendb
372 (map (lambda (x) (ascii->upm-string (char->integer x)))
373 (string->list s))))))