]> git.donarmstrong.com Git - lilypond.git/blob - scm/output-ps.scm
*** empty log message ***
[lilypond.git] / scm / output-ps.scm
1 ;;;; output-ps.scm -- implement Scheme output interface for PostScript
2 ;;;;
3 ;;;;  source file of the GNU LilyPond music typesetter
4 ;;;; 
5 ;;;; (c) 1998--2006 Jan Nieuwenhuizen <janneke@gnu.org>
6 ;;;;                 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7
8 ;;;; Note: currently misused as testbed for titles with markup, see
9 ;;;;       input/test/title-markup.ly
10 ;;;; 
11 ;;;; TODO:
12 ;;;;   * %% Papersize in (header ...)
13 ;;;;   * text setting, kerning.
14 ;;;;   * document output-interface
15
16 (define-module (scm output-ps)
17   #:re-export (quote)
18
19   ;; JUNK this -- see lily.scm: ly:all-output-backend-commands
20   #:export (unknown
21             blank
22             circle
23             dot
24             dashed-slur
25             char
26             setcolor
27             resetcolor
28             named-glyph
29             dashed-line
30             zigzag-line
31             comment
32             repeat-slash
33             placebox
34             bezier-sandwich
35             embedded-ps
36             round-filled-box
37             text
38             polygon
39             draw-line
40             no-origin))
41
42
43 (use-modules (guile)
44              (ice-9 regex)
45              (srfi srfi-1)
46              (srfi srfi-13)
47              (scm framework-ps)
48              (lily))
49
50 ;;; helper functions, not part of output interface
51 ;;;
52
53
54 (define (escape-parentheses s)
55   (regexp-substitute/global #f "(^|[^\\])([\\(\\)])" s 'pre 1 "\\" 2 'post))
56
57 (define (ps-encoding text)
58   (escape-parentheses text))
59
60 (define (round2 num)
61   (/ (round (* 100 num)) 100))
62
63 (define (round4 num)
64   (/ (round (* 10000 num)) 10000))
65
66 (define (str4 num)
67   (format #f "~f" (round4 num)))
68
69 (define (number-pair->string4 numpair)
70   (format #f "~f ~f" (round4 (car numpair)) (round4 (cdr numpair))))
71
72 (define (numbers->string4 numlist)
73   (string-join (map str4 numlist) " "))
74
75 ;; FIXME: lily-def
76 (define-public (ps-string-def prefix key val)
77   (format #f "/ ~a~a (~a) def\n"
78           prefix
79           (symbol->string key)
80           (escape-parentheses val)))
81
82 (define (ps-number-def prefix key val)
83   (let ((s (if (integer? val)
84                (ly:number->string val)
85                (ly:number->string (exact->inexact val)))))
86     (format #f "/~a~a ~a def\n"
87             prefix
88             (symbol->string key) s)))
89
90
91 ;;;
92 ;;; Lily output interface, PostScript implementation --- cleanup and docme
93 ;;;
94
95 ;; two beziers
96 (define (bezier-sandwich lst thick)
97   (format #f "~a ~a draw_bezier_sandwich" 
98           (string-join (map number-pair->string4 lst) " ")
99           (str4 thick)))
100
101 (define (char font i)
102   (format #f "~a (\\~a) show"
103    (ps-font-command font)
104    (ly:inexact->string i 8)))
105
106 (define (circle radius thick fill)
107   (format #f
108    "~a ~f ~f draw_circle"
109    (if fill
110      "true"
111      "false")
112    (round4 radius) (round4 thick)))
113
114 (define (dashed-line thick on off dx dy)
115   (format #f "~a ~a ~a [ ~a ~a ] 0 draw_dashed_line"
116    (str4 dx)
117    (str4 dy)
118    (str4 thick)
119    (str4 on)
120    (str4 off)))
121
122 ;; what the heck is this interface ?
123 (define (dashed-slur thick on off l)
124   (format #f "~a ~a [ ~a ~a ] 0 draw_dashed_slur"
125           (string-join (map number-pair->string4 l) " ")
126           (str4 thick)
127           (str4 on)
128           (str4 off)))
129
130 (define (dot x y radius)
131   (format #f " ~a draw_dot"
132    (numbers->string4 (list x y radius))))
133
134 (define (draw-line thick x1 y1 x2 y2)
135   (format #f "1 setlinecap 1 setlinejoin ~a setlinewidth ~a ~a moveto ~a ~a lineto stroke"
136    (str4 thick)
137    (str4 x1)
138    (str4 y1)
139    (str4 x2)
140    (str4 y2)))
141
142 (define (embedded-ps string)
143   string)
144
145 (define (glyph-string postscript-font-name
146                       size
147                       cid?
148                       w-x-y-named-glyphs)
149
150   (define (glyph-spec w x y g)
151     (let ((prefix (if (string? g) "/" "")))
152       (format #f "~f ~f ~a~a"
153               (round2 (+ w x))
154               (round2 y)
155               prefix g)))
156   
157   (format #f
158           (if cid?
159 "gsave
160 /~a /CIDFont findresource ~a output-scale div scalefont setfont
161 ~a
162 ~a print_glyphs
163 grestore"
164
165 "gsave\n/~a ~a output-scale div selectfont
166 ~a
167 ~a print_glyphs
168 grestore")
169           postscript-font-name
170           size
171           (string-join (map (lambda (x) (apply glyph-spec x))
172                             (reverse w-x-y-named-glyphs)) "\n")
173           (length w-x-y-named-glyphs)))
174
175
176 (define (grob-cause offset grob)
177   (let* ((cause (ly:grob-property grob 'cause))
178          (music-origin (if (ly:music? cause)
179                            (ly:music-property cause 'origin))))
180     (if (not (ly:input-location? music-origin))
181         ""
182         (let* ((location (ly:input-file-line-char-column music-origin))
183                (raw-file (car location))
184                (file (if (is-absolute? raw-file)
185                          raw-file
186                          (string-append (ly-getcwd) "/" raw-file)))
187                (x-ext (ly:grob-extent grob grob X))
188                (y-ext (ly:grob-extent grob grob Y)))
189
190           (if (and (< 0 (interval-length x-ext))
191                    (< 0 (interval-length y-ext)))
192               (format #f "~$ ~$ ~$ ~$ (textedit://~a:~a:~a:~a) mark_URI\n"
193                       (+ (car offset) (car x-ext))
194                       (+ (cdr offset) (car y-ext))
195                       (+ (car offset) (cdr x-ext))
196                       (+ (cdr offset) (cdr y-ext))
197
198                       ;; TODO
199                       ;;full escaping.
200
201                       ;; backslash is interpreted by GS.
202                       (string-regexp-substitute "\\\\" "/" 
203                                       (string-regexp-substitute " " "%20" file))
204                       (cadr location)
205                       (caddr location)
206                       (cadddr location))
207               "")))))
208
209 (define (lily-def key val)
210   (let ((prefix "lilypondlayout"))
211     (if (string=?
212           (substring key 0 (min (string-length prefix) (string-length key)))
213           prefix)
214       (format "/~a { ~a } bind def\n" key val)
215       (format "/~a (~a) def\n" key val))))
216
217 (define (named-glyph font glyph)
218   (format #f "~a /~a glyphshow " ;;Why is there a space at the end?
219           (ps-font-command font)
220           glyph))
221
222 (define (no-origin)
223   "")
224
225 (define (placebox x y s) 
226   (format #f
227 "gsave ~a ~a translate
228 0 0 moveto
229 ~a
230 grestore\n"
231
232   (str4 x)
233   (str4 y)
234   s))
235
236 (define (polygon points blot-diameter filled?)
237   (format #f "~a ~a ~a ~a draw_polygon"
238           (if filled? "true" "false")
239           (numbers->string4 points)
240           (number->string (- (/ (length points) 2) 1))
241           (str4 blot-diameter)))
242
243 (define (repeat-slash width slope beam-thickness)
244   (define (euclidean-length x y)
245     (sqrt (+ (* x x) (* y y))))
246
247   (let ((x-width (euclidean-length slope (/ beam-thickness slope)))
248         (height (* width slope)))
249     (format #f "~a draw_repeat_slash"
250             (numbers->string4 (list x-width width height)))))
251
252 ;; restore color from stack
253 (define (resetcolor) "setrgbcolor\n")
254
255 (define (round-filled-box left right bottom top blotdiam)
256   (let* ((halfblot (/ blotdiam 2))
257          (x (- halfblot left))
258          (width (- right (+ halfblot x)))
259          (y (- halfblot bottom))
260          (height (- top (+ halfblot y))))
261     (format #f "~a draw_round_box"
262             (numbers->string4
263               (list x y width height blotdiam)))))
264
265 ;; save current color on stack and set new color
266 (define (setcolor r g b)
267   (format #f "currentrgbcolor ~a setrgbcolor\n"
268           (numbers->string4 (list r g b))))
269
270 (define (text font s)
271   ;; (ly:warning (_ "TEXT backend-command encountered in Pango backend"))
272   ;; (ly:warning (_ "Arguments: ~a ~a"" font str))
273   
274   (let* ((space-length (cdar (ly:text-dimension font " ")))
275          (space-move (string-append (number->string space-length)
276                                     ;; how much precision do we need here?
277                                     " 0.0 rmoveto "))
278          (out-vec (decode-byte-string s)))
279
280     (string-append
281      (ps-font-command font) " "
282      (string-join
283       (vector->list
284        (vector-for-each
285         
286         (lambda (sym)
287           (if (eq? sym 'space)
288               space-move
289               (string-append "/" (symbol->string sym) " glyphshow")))
290         out-vec))))))
291
292 (define (unknown) 
293   "\n unknown\n")
294
295 (define (url-link url x y)
296   (format #f "~$ ~$ ~$ ~$ (~a) mark_URI"
297           (car x)
298           (car y)
299           (cdr x)
300           (cdr y)
301           url))
302
303 (define (utf-8-string pango-font-description string)
304   (ly:warning (_ "utf-8-string encountered in PS backend")))
305
306
307 (define (zigzag-line centre? zzw zzh thick dx dy)
308   (format #f "~a ~a ~a ~a 0 0 ~a ~a draw_zigzag_line"
309    (if centre? "true" "false")
310    (str4 zzw)
311    (str4 zzh)
312    (str4 thick)
313    (str4 dx)
314    (str4 dy)))