]> 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           (let ((control-points (append (cddr l) (list (car l) (cadr l)))))
126             (string-join (map number-pair->string4 control-points) " "))
127           (str4 thick)
128           (str4 on)
129           (str4 off)))
130
131 (define (dot x y radius)
132   (format #f " ~a draw_dot"
133    (numbers->string4 (list radius x y))))
134
135 (define (draw-line thick x1 y1 x2 y2)
136   (format #f "~a ~a ~a ~a ~a draw_line"
137           (str4 (- x2 x1))
138           (str4 (- y2 y1))
139           (str4 x1)
140           (str4 y1)
141           (str4 thick)))
142
143 (define (embedded-ps string)
144   string)
145
146 (define (glyph-string postscript-font-name
147                       size
148                       cid?
149                       w-x-y-named-glyphs)
150
151   (define (glyph-spec w x y g)
152     (let ((prefix (if (string? g) "/" "")))
153       (format #f "~f ~f ~a~a"
154               (round2 (+ w x))
155               (round2 y)
156               prefix g)))
157   
158   (format #f
159           (if cid?
160 "/~a /CIDFont findresource ~a output-scale div scalefont setfont
161 ~a
162 ~a print_glyphs"
163
164 "/~a ~a output-scale div selectfont
165 ~a
166 ~a print_glyphs")
167           postscript-font-name
168           size
169           (string-join (map (lambda (x) (apply glyph-spec x))
170                             (reverse w-x-y-named-glyphs)) "\n")
171           (length w-x-y-named-glyphs)))
172
173
174 (define (grob-cause offset grob)
175   (let* ((cause (ly:grob-property grob 'cause))
176          (music-origin (if (ly:music? cause)
177                            (ly:music-property cause 'origin))))
178     (if (not (ly:input-location? music-origin))
179         ""
180         (let* ((location (ly:input-file-line-char-column music-origin))
181                (raw-file (car location))
182                (file (if (is-absolute? raw-file)
183                          raw-file
184                          (string-append (ly-getcwd) "/" raw-file)))
185                (x-ext (ly:grob-extent grob grob X))
186                (y-ext (ly:grob-extent grob grob Y)))
187
188           (if (and (< 0 (interval-length x-ext))
189                    (< 0 (interval-length y-ext)))
190               (format #f "~$ ~$ ~$ ~$ (textedit://~a:~a:~a:~a) mark_URI\n"
191                       (+ (car offset) (car x-ext))
192                       (+ (cdr offset) (car y-ext))
193                       (+ (car offset) (cdr x-ext))
194                       (+ (cdr offset) (cdr y-ext))
195
196                       ;; TODO
197                       ;;full escaping.
198
199                       ;; backslash is interpreted by GS.
200                       (string-regexp-substitute "\\\\" "/" 
201                                       (string-regexp-substitute " " "%20" file))
202                       (cadr location)
203                       (caddr location)
204                       (cadddr location))
205               "")))))
206
207 (define (lily-def key val)
208   (let ((prefix "lilypondlayout"))
209     (if (string=?
210           (substring key 0 (min (string-length prefix) (string-length key)))
211           prefix)
212       (format "/~a { ~a } bind def\n" key val)
213       (format "/~a (~a) def\n" key val))))
214
215 (define (named-glyph font glyph)
216   (format #f "~a /~a glyphshow " ;;Why is there a space at the end?
217           (ps-font-command font)
218           glyph))
219
220 (define (no-origin)
221   "")
222
223 (define (placebox x y s) 
224   (format #f
225 "~a ~a moveto
226 ~a\n"
227   (str4 x)
228   (str4 y)
229   s))
230
231 (define (polygon points blot-diameter filled?)
232   (format #f "~a ~a ~a ~a draw_polygon"
233           (if filled? "true" "false")
234           (numbers->string4 points)
235           (number->string (- (/ (length points) 2) 1))
236           (str4 blot-diameter)))
237
238 (define (repeat-slash width slope beam-thickness)
239   (define (euclidean-length x y)
240     (sqrt (+ (* x x) (* y y))))
241
242   (let ((x-width (euclidean-length slope (/ beam-thickness slope)))
243         (height (* width slope)))
244     (format #f "~a draw_repeat_slash"
245             (numbers->string4 (list x-width width height)))))
246
247 ;; restore color from stack
248 (define (resetcolor) "setrgbcolor\n")
249
250 (define (round-filled-box left right bottom top blotdiam)
251   (let* ((halfblot (/ blotdiam 2))
252          (x (- halfblot left))
253          (width (- right (+ halfblot x)))
254          (y (- halfblot bottom))
255          (height (- top (+ halfblot y))))
256     (format #f "~a draw_round_box"
257             (numbers->string4
258               (list width height x y blotdiam)))))
259
260 ;; save current color on stack and set new color
261 (define (setcolor r g b)
262   (format #f "currentrgbcolor ~a setrgbcolor\n"
263           (numbers->string4 (list r g b))))
264
265 (define (text font s)
266   ;; (ly:warning (_ "TEXT backend-command encountered in Pango backend"))
267   ;; (ly:warning (_ "Arguments: ~a ~a"" font str))
268   
269   (let* ((space-length (cdar (ly:text-dimension font " ")))
270          (space-move (string-append (number->string space-length)
271                                     ;; how much precision do we need here?
272                                     " 0.0 rmoveto "))
273          (out-vec (decode-byte-string s)))
274
275     (string-append
276      (ps-font-command font) " "
277      (string-join
278       (vector->list
279        (vector-for-each
280         
281         (lambda (sym)
282           (if (eq? sym 'space)
283               space-move
284               (string-append "/" (symbol->string sym) " glyphshow")))
285         out-vec))))))
286
287 (define (unknown) 
288   "\n unknown\n")
289
290 (define (url-link url x y)
291   (format #f "~$ ~$ ~$ ~$ (~a) mark_URI"
292           (car x)
293           (car y)
294           (cdr x)
295           (cdr y)
296           url))
297
298 (define (utf-8-string pango-font-description string)
299   (ly:warning (_ "utf-8-string encountered in PS backend")))
300
301
302 (define (zigzag-line centre? zzw zzh thick dx dy)
303   (format #f "~a ~a ~a ~a 0 0 ~a ~a draw_zigzag_line"
304    (if centre? "true" "false")
305    (str4 zzw)
306    (str4 zzh)
307    (str4 thick)
308    (str4 dx)
309    (str4 dy)))