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 to create the .pfa fonts:
14 ;;;; * Get sodipodi-0.28 or newer
16 ;;;; * Link/copy mf/out/private-fonts to ~/.sodipodi/private-fonts
18 ;;;; http://www.w3.org/TR/SVG11/paths.html
21 (debug-enable 'backtrace)
23 (define-module (scm sodipodi))
24 (define this-module (current-module))
30 ;;; Lily output interface --- cleanup and docme
32 ;;; Bare minimum interface for \score { \notes c } }
35 ;;; xx-output-expression
40 ;;; and should intercept:
54 ;;(define-public (sodipodi-output-expression expr port)
55 ;; (display (eval expr this-module) port))
57 (define-public (sodipodi-output-expression expr port)
58 (display (dispatch expr) port))
60 (define (dispatch expr)
61 (let ((keyword (car expr)))
63 ((eq? keyword 'some-func) "")
64 ;;((eq? keyword 'placebox) (dispatch (cadddr expr)))
65 ;;((eq? keyword 'fontify) (dispatch (caddr expr)))
67 (if (module-defined? this-module keyword)
68 (apply (eval keyword this-module) (cdr expr))
71 (string-append "undefined: " (symbol->string keyword) "\n"))
77 (define output-scale 1)
80 (define urg-line-thickness 0)
81 (define line-thickness 0.001)
82 (define half-lt (/ line-thickness 2))
87 ((equal? (ly:unit) "mm") (/ 72.0 25.4))
88 ((equal? (ly:unit) "pt") (/ 72.0 72.27))
89 (else (error "unknown unit" (ly:unit)))))
91 ;; alist containing fontname -> fontcommand assoc (both strings)
92 ;;(define font-name-alist '())
97 (define (tagify tag string . attribute-alist)
100 (apply string-append (map (lambda (x) (string-append
102 (symbol->string (car x))
108 string "\n</" tag ">\n"))
111 (define (ascii->string i) (make-string 1 (integer->char i)))
112 (define (ascii->upm-string i)
115 (u2 (+ #x80 (quotient i+1 #x40)))
116 (u3 (+ #x80 (modulo i+1 #x40))))
121 (define (control->list c)
122 (list (car c) (cdr c)))
124 (define (control->string c)
126 (number->string (car c)) ","
128 (number->string (* -1 (cdr c))) " "))
130 (define (control-flip-y c)
131 (cons (car c) (* -1 (cdr c))))
133 (define (numbers->string l)
135 (number->string (car l))
138 (string-append "," (numbers->string (cdr l))))))
140 (define (svg-bezier l close)
141 (let* ((c0 (car (list-tail l 3)))
142 (c123 (list-head l 3)))
144 (if (not close) "M " "L ")
146 "C " (apply string-append (map control->string c123))
147 (if (not close) "" (string-append
148 "L " (control->string close))))));; " Z")))))
151 "<?xml version='1.0' standalone='no'?>
152 <!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 20010904//EN'
153 'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'
156 xmlns:xlink CDATA #FIXED 'http://www.w3.org/1999/xlink'>
165 sodipodi:version='0.26'
166 xmlns='http://www.w3.org/2000/svg'
167 xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'
168 xmlns:xlink='http://www.w3.org/1999/xlink'
171 sodipodi:docbase='/tmp/'
172 sodipodi:docname='/tmp/x'>
177 <g transform='translate(10,10) scale (1.0)'>
182 ;; Interface functions
187 ;; transform=scale and stroke don't play nice together...
188 (define (XXXbeam width slope thick)
191 (z (sqrt (+ (sqr x) (sqr y)))))
193 ;; '(style . "fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-opacity:1;stroke-width:0.1;stroke-linejoin:miter;stroke-linecap:butt;")
194 ;;'(style . "fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-opacity:1;stroke-width:0.000001;stroke-linejoin:miter;stroke-linecap:butt;")
195 `(style . ,(format "fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-opacity:1;stroke-width:~f;stroke-linejoin:miter;stroke-linecap:butt;" line-thickness))
196 ;;`(x . ,(number->string half-lt))
198 ;;`(y . ,(number->string (- half-lt (/ thick 2))))
199 `(y . ,(number->string (- 0 (/ thick 2))))
200 `(width . ,(number->string width))
201 `(height . ,(number->string thick))
202 `(ry . ,(number->string half-lt))
203 `(transform . ,(format #f "matrix(~f,~f,0,1,0,0) scale (~f,~f)"
206 output-scale output-scale)))))
208 (define (beam width slope thick)
211 (z (sqrt (+ (sqr x) (sqr y)))))
213 `(style . ,(format "fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-opacity:1;stroke-width:~f;stroke-linejoin:miter;stroke-linecap:butt;" line-thickness))
215 `(y . ,(number->string (* output-scale (- 0 (/ thick 2)))))
216 `(width . ,(number->string (* output-scale width)))
217 `(height . ,(number->string (* output-scale thick)))
218 `(ry . ,(number->string (* output-scale half-lt)))
219 `(transform . ,(format #f "matrix(~f,~f,0,1,0,0) scale (~f,~f)"
224 ;; TODO: bezier-ending, see ps.scm
225 (define (bezier-bow urg-l thick)
227 (define (bezier-ending z0 z1 z2)
234 (let ((r (/ (sqrt (+ (* (- x1 x2) (- x1 x2))
235 (* (- y1 y2) (- y1 y2)))) 2)))
238 `(cx . ,(number->string (* output-scale x0)))
239 `(cy . ,(number->string (* output-scale (- 0 y0))))
240 `(r . ,(number->string (* output-scale r)))))))
242 (let ((l (eval urg-l this-module)))
244 (bezier-sandwich l thick)
245 (bezier-ending (list-ref l 3) (list-ref l 0) (list-ref l 5))
246 (bezier-ending (list-ref l 7) (list-ref l 0) (list-ref l 5)))))
248 (define (bezier-sandwich l thick)
249 (let* (;;(l (eval urg-l this-module))
250 (first (list-tail l 4))
251 (first-c0 (car (list-tail first 3)))
252 (second (list-head l 4)))
254 `(stroke . "#000000")
255 `(stroke-width . ,(number->string line-thickness))
256 `(transform . ,(format #f "scale (~f,~f)"
257 output-scale output-scale))
258 `(d . ,(string-append (svg-bezier first #f)
259 (svg-bezier second first-c0))))))
263 ;;(tagify "tspan" (format #f "à~2,'0x;" i))
264 (tagify "tspan" (ascii->upm-string i))
266 (format #t "can't display char: ~x\n" i)
271 (string-append "<!-- " s " -->\n"))
273 (define (define-fonts internal-external-name-mag-pairs)
274 (comment (format #f "Fonts used: ~S" internal-external-name-mag-pairs)))
279 (define (filledbox breapth width depth height)
280 (roundfilledbox breapth width depth height line-thickness))
283 "fill:black;stroke:none;text-anchor:start;writing-mode:lr;font-weight:normal;")
288 ("cmr8" . ,(string-append
290 "font-family:cmr;font-style:normal;font-size:8;"))
291 ("feta13" . ,(string-append
293 "font-family:LilyPond-Feta;font-style:-Feta;font-size:13;"))
294 ("feta-nummer10" . ,(string-append
296 "font-family:LilyPond-feta-nummer;font-style:-feta-nummer;font-size:10;"))
297 ("feta20" . ,(string-append
299 "font-family:LilyPond-feta;font-style:-feta;font-size:20;"))
300 ("parmesan20" . ,(string-append
302 "font-family:LilyPond-Parmesan;font-style:-Parmesan;font-size:20;"))))
304 (define (get-font name-mag-pair)
305 ;; name-mag-pair: (quote ("feta20" . 0.569055118110236))"feta20"(quote ("feta20" . 0.569055118110236))
306 (let ((f (assoc (caadr name-mag-pair) font-alist)))
310 (format #t "font not found: ~s\n" (caadr name-mag-pair))
311 (cdr (assoc "feta20" font-alist))))))
313 (define (fontify name-mag-pair expr)
315 (tagify "text" (dispatch expr) (cons 'style (get-font name-mag-pair)))))
318 (comment "header-end"))
320 (define (header creator generate)
328 (define (lily-def key val)
330 ((equal? key "lilypondpaperoutputscale")
332 ;; If we just use transform scale (output-scale),
333 ;; all fonts come out scaled too (ie, much too big)
334 ;; So, we manually scale all other stuff.
335 (set! output-scale (* scale-to-unit (string->number val))))
336 ((equal? key "lilypondpaperlinethickness")
337 (set! urg-line-thickness (* scale-to-unit (string->number val)))))
344 (define (placebox x y expr)
345 (tagify "g" (dispatch expr)
350 (number->string (* output-scale x))
352 (number->string (- 0 (* output-scale y)))
355 (define (roundfilledbox breapth width depth height blot-diameter)
357 ;;'(style . "fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;")
358 `(style . ,(format "fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-opacity:1;stroke-width:~f;stroke-linejoin:miter;stroke-linecap:butt;" line-thickness))
359 `(x . ,(number->string (* output-scale (- 0 breapth))))
360 `(y . ,(number->string (* output-scale (- 0 height))))
361 `(width . ,(number->string (* output-scale (+ breapth width))))
362 `(height . ,(number->string (* output-scale (+ depth height))))
363 ;;`(ry . ,(number->string (* output-scale half-lt)))
364 `(ry . ,(number->string (/ blot-diameter 2)))))
368 ;; TODO: use height, set scaling?
369 (define (start-system width height)
371 ;;"<g transform='translate(50,-250)'>
372 (set! system-y (+ system-y height))
373 ;;(format #f "<g transform='translate(0,~1,'~f)'>" y)))
376 (comment "start-system")
377 (format #f "<g transform='translate(0.0,~f)'>\n" (* output-scale y)))))
379 (define (stop-system)
382 (comment "stop-system")
385 (define stop-last-system stop-system)
388 ;; to unicode or not?
392 (apply string-appendb
393 (map (lambda (x) (ascii->upm-string (char->integer x)))
394 (string->list s))))))