]> git.donarmstrong.com Git - lilypond.git/blob - scm/output-tex.scm
(define-fonts):
[lilypond.git] / scm / output-tex.scm
1 ;;;; tex.scm -- implement Scheme output routines for TeX
2 ;;;;
3 ;;;;  source file of the GNU LilyPond music typesetter
4 ;;;; 
5 ;;;; (c)  1998--2004 Jan Nieuwenhuizen <janneke@gnu.org>
6 ;;;;                  Han-Wen Nienhuys <hanwen@cs.uu.nl>
7
8
9 ;; (debug-enable 'backtrace)
10 (define-module (scm output-tex)
11   #:re-export (quote)
12   #:export (define-fonts
13              font-command
14              fontify
15              unknown
16              output-paper-def
17              output-scopes
18              blank
19              dot
20              beam
21              bracket
22              dashed-slur
23              char
24              dashed-line
25              zigzag-line
26              symmetric-x-triangle
27              ez-ball
28              comment
29              end-output
30              experimental-on
31              repeat-slash
32              header-end
33              header
34              placebox
35              bezier-sandwich
36              start-system
37              stop-system
38              stop-last-system
39              horizontal-line
40              filledbox
41              round-filled-box
42              text
43              tuplet
44              polygon
45              draw-line
46              between-system-string
47              define-origin
48              no-origin
49              start-page
50              stop-page
51              )
52 )
53
54 (use-modules (ice-9 regex)
55              (ice-9 string-fun)
56              (ice-9 format)
57              (guile)
58              (srfi srfi-13)
59              (lily))
60
61 ;;;;;;;;
62 ;;;;;;;; DOCUMENT ME!
63 ;;;;;;;;
64
65 (define (font-command font)
66   (string-append
67    "magfont"
68    (string-encode-integer
69     (hashq (ly:font-name font) 1000000))
70    "m"
71    (string-encode-integer
72     (inexact->exact (round (* 1000 (ly:font-magnification font)))))))
73
74 (define (define-fonts paper font-list)
75   (apply string-append
76          (map (lambda (x) (font-load-command paper x)) font-list)))
77
78 (define (fontify font exp)
79   (string-append "\\" (font-command font) exp))
80
81 (define (unknown) 
82   "%\n\\unknown\n")
83
84 (define (symbol->tex-key sym)
85   (regexp-substitute/global
86    #f "_" (output-tex-string (symbol->string sym)) 'pre "X" 'post) )
87
88 (define (tex-string-def prefix key str)
89   (if (equal? "" (sans-surrounding-whitespace (output-tex-string str)))
90       (string-append "\\let\\" prefix (symbol->tex-key key) "\\undefined%\n")
91       (string-append "\\def\\" prefix (symbol->tex-key key) "{"  (output-tex-string str) "}%\n")
92       ))
93
94 (define (tex-number-def prefix key number)
95   (string-append "\\def\\" prefix (symbol->tex-key key) "{" number "}%\n"))
96
97 (define (output-paper-def pd)
98   (apply
99    string-append
100    (module-map
101     (lambda (sym var)
102       (let ((val (variable-ref var))
103             (key (symbol->tex-key sym)))
104
105         (cond
106          ((string? val)
107           (tex-string-def "lilypondpaper" sym val))
108          ((number? val)
109           (tex-number-def "lilypondpaper" sym
110                           (if (integer? val)
111                               (number->string val)
112                               (number->string (exact->inexact val)))))
113          (else ""))))
114       
115     (ly:output-def-scope pd))))
116
117 (define (output-scopes paper scopes fields basename)
118   (define (output-scope scope)
119     (apply
120      string-append
121      (module-map
122      (lambda (sym var)
123        (let ((val (variable-ref var))
124              ;;(val (if (variable-bound? var) (variable-ref var) '""))
125              (tex-key (symbol->string sym)))
126          
127          (if (and (memq sym fields) (string? val))
128              (header-to-file basename sym val))
129
130          (cond
131           ((string? val)
132            (tex-string-def "lilypond" sym val))
133           ((number? val)
134            (tex-number-def "lilypond" sym
135                            (if (integer? val)
136                                (number->string val)
137                                (number->string (exact->inexact val)))))
138           (else ""))))
139      scope)))
140   
141   (apply string-append
142          (map output-scope scopes)))
143
144 (define (blank)
145   "")
146
147 (define (dot x y radius)
148   (embedded-ps (list 'dot x y radius)))
149
150 (define (beam width slope thick blot)
151   (embedded-ps (list 'beam  width slope thick blot)))
152
153 (define (bracket arch_angle arch_width arch_height height arch_thick thick)
154   (embedded-ps (list 'bracket  arch_angle arch_width arch_height height arch_thick thick)))
155
156 (define (dashed-slur thick dash l)
157   (embedded-ps (list 'dashed-slur thick dash `(quote ,l))))
158
159 (define (char i)
160   (string-append "\\char" (ly:inexact->string i 10) " "))
161
162 (define (dashed-line thick on off dx dy)
163   (embedded-ps (list 'dashed-line  thick on off dx dy)))
164
165 (define (zigzag-line centre? zzw zzh thick dx dy)
166   (embedded-ps (list 'zigzag-line centre? zzw zzh thick dx dy)))
167
168 (define (symmetric-x-triangle t w h)
169   (embedded-ps (list 'symmetric-x-triangle t w h)))
170
171 (define (font-load-command paper font)
172   (string-append
173    "\\font\\" (font-command font) "="
174    (ly:font-name font)
175    " scaled "
176    (ly:number->string (inexact->exact
177                        (round (* 1000
178                           (ly:font-magnification font)
179                           (ly:paper-lookup paper 'outputscale)))))
180    "\n"))
181
182 (define (ez-ball c l b)
183   (embedded-ps (list 'ez-ball  c  l b)))
184
185 (define (header-to-file fn key val)
186   (set! key (symbol->string key))
187   (if (not (equal? "-" fn))
188       (set! fn (string-append fn "." key))
189       )
190   (display
191    (format "writing header field `~a' to `~a'..."
192            key
193            (if (equal? "-" fn) "<stdout>" fn)
194            )
195    (current-error-port))
196   (if (equal? fn "-")
197       (display val)
198       (display val (open-file fn "w"))
199   )
200   (display "\n" (current-error-port))
201   ""
202   )
203
204 (define (embedded-ps expr)
205   (let ((ps-string
206          (with-output-to-string
207            (lambda () (ps-output-expression expr (current-output-port))))))
208     (string-append "\\embeddedps{" ps-string "}")))
209   
210 (define (comment s)
211   (string-append "% " s "\n"))
212
213 (define (end-output) 
214   (begin
215     ;; uncomment for some stats about lily memory         
216     ;; (display (gc-stats))
217     (string-append
218      "\\lilypondend\n"
219      ;; Put GC stats here.
220      )))
221
222 (define (experimental-on)
223   "")
224
225 (define (repeat-slash w a t)
226   (embedded-ps (list 'repeat-slash  w a t)))
227
228 (define (header-end)
229   (string-append
230    "\\def\\scaletounit{ "
231    (number->string (cond
232                      ((equal? (ly:unit) "mm") (/ 72.0  25.4))
233                      ((equal? (ly:unit) "pt") (/ 72.0  72.27))
234                      (else (error "unknown unit" (ly:unit)))
235                      ))
236    " mul }%\n"
237    "\\ifx\\lilypondstart\\undefined\n"
238    "  \\input lilyponddefs\n"
239    "\\fi\n"
240    "\\outputscale = \\lilypondpaperoutputscale\\lilypondpaperunit\n"
241    "\\lilypondstart\n"
242    "\\lilypondspecial\n"
243    "\\lilypondpostscript\n"))
244
245 (define (header creator time-stamp page-count)
246   (string-append
247    "% Generated by " creator "\n"
248    "% at " time-stamp "\n"
249    ;; FIXME: duplicated in every backend
250    "\\def\\lilypondtagline{Engraved by LilyPond (version "
251    (lilypond-version)")}\n"))
252
253 (define (invoke-char s i)
254   (string-append 
255    "\n\\" s "{" (ly:inexact->string i 10) "}" ))
256
257 ;; FIXME: explain ploblem: need to do something to make this really safe.  
258 (define (output-tex-string s)
259   (if safe-mode?
260       (regexp-substitute/global #f "\\\\" s 'pre "$\\backslash$" 'post)
261       s))
262
263 (define (lily-def key val)
264   (let ((tex-key
265          (regexp-substitute/global
266               #f "_" (output-tex-string key) 'pre "X" 'post))
267          
268         (tex-val (output-tex-string val)))
269     (if (equal? (sans-surrounding-whitespace tex-val) "")
270         (string-append "\\let\\" tex-key "\\undefined\n")
271         (string-append "\\def\\" tex-key "{" tex-val "}%\n"))))
272
273 (define (number->dim x)
274   (string-append
275    ;;ugh ly:* in backend needs compatibility func for standalone output
276    (ly:number->string x) " \\outputscale "))
277
278 (define (placebox x y s) 
279   (string-append "\\lyitem{"
280                  (ly:number->string y) "}{"
281                  (ly:number->string x) "}{"
282                  s "}%\n"))
283
284 (define (bezier-sandwich l thick)
285   (embedded-ps (list 'bezier-sandwich  `(quote ,l) thick)))
286
287 (define (start-system wd ht)
288   (string-append "\\leavevmode\n"
289                  "\\scoreshift = " (number->dim (* ht 0.5)) "\n"
290                  "\\lilypondifundefined{lilypondscoreshift}%\n"
291                  "  {}%\n"
292                  "  {\\advance\\scoreshift by -\\lilypondscoreshift}%\n"
293                  "\\lybox{"
294                  (ly:number->string wd) "}{"
295                  (ly:number->string ht) "}{%\n"))
296
297 (define (stop-system) 
298   "}%\n%\n\\interscoreline\n%\n")
299 (define (stop-last-system)
300   "}%\n")
301
302 (define (horizontal-line x1 x2 th)
303   (filledbox (- x1)  (- x2 x1) (* .5 th)  (* .5 th )))
304
305 (define (filledbox breapth width depth height)
306   (if (and #f (defined? 'ps-testing))
307       (embedded-ps
308        (string-append (ly:numbers->string (list breapth width depth height))
309                       " draw_box" ))
310       (string-append "\\lyvrule{"
311                      (ly:number->string (- breapth)) "}{"
312                      (ly:number->string (+ breapth width)) "}{"
313                      (ly:number->string depth) "}{"
314                      (ly:number->string height) "}")))
315
316 (define (round-filled-box x y width height blotdiam)
317   (embedded-ps (list 'round-filled-box  x y width height blotdiam)))
318
319 (define (text s)
320   (string-append "\\hbox{" (output-tex-string s) "}"))
321
322 (define (tuplet ht gapx dx dy thick dir)
323   (embedded-ps (list 'tuplet  ht gapx dx dy thick dir)))
324
325 (define (polygon points blotdiameter)
326   (embedded-ps (list 'polygon `(quote ,points) blotdiameter)))
327
328 (define (draw-line thick fx fy tx ty)
329   (embedded-ps (list 'draw-line thick fx fy tx ty)))
330
331 ;; TODO: this should be a default, which is overriden in PS
332 (define (between-system-string string)
333   string
334   )
335 (define (define-origin file line col)
336   (if (procedure? point-and-click)
337       (string-append "\\special{src:" ;;; \\string ? 
338                      (point-and-click line col file)
339                      "}" )
340       "")
341   )
342
343 ;; no-origin not yet supported by Xdvi
344 (define (no-origin) "")
345
346 (define (start-page)
347   "\n%\\vbox{\n")
348
349 (define (stop-page last?)
350   (if last?
351       "\n%}\n"
352       "\n%}\n\\newpage\n"))