Doc: CG: Improve sectioning; update nodes and menus
[lilypond/mpolesky.git] / scm / output-ps.scm
blob06b324b799c7abd07f10c1518ead850bd897724e
1 ;;;; This file is part of LilyPond, the GNU music typesetter.
2 ;;;;
3 ;;;; Copyright (C) 1998--2010 Jan Nieuwenhuizen <janneke@gnu.org>
4 ;;;;                 Han-Wen Nienhuys <hanwen@xs4all.nl>
5 ;;;;
6 ;;;; LilyPond is free software: you can redistribute it and/or modify
7 ;;;; it under the terms of the GNU General Public License as published by
8 ;;;; the Free Software Foundation, either version 3 of the License, or
9 ;;;; (at your option) any later version.
10 ;;;;
11 ;;;; LilyPond is distributed in the hope that it will be useful,
12 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ;;;; GNU General Public License for more details.
15 ;;;;
16 ;;;; You should have received a copy of the GNU General Public License
17 ;;;; along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
19 ;;;; Note: currently misused as testbed for titles with markup, see
20 ;;;;       input/test/title-markup.ly
21 ;;;; 
22 ;;;; TODO:
23 ;;;;   * %% Papersize in (header ...)
24 ;;;;   * text setting, kerning.
25 ;;;;   * document output-interface
27 (define-module (scm output-ps)
28   #:re-export (quote))
30 (use-modules (guile)
31              (ice-9 regex)
32              (srfi srfi-1)
33              (srfi srfi-13)
34              (scm framework-ps)
35              (lily))
37 ;;; helper functions, not part of output interface
38 ;;;
41 ;; ice-9 format uses a lot of memory
42 ;; using simple-format almost halves lilypond cell usage
44 (define (str4 num)
45   (if (or (nan? num) (inf? num))
46       (begin
47         (ly:warning (_ "Found infinity or nan in output. Substituting 0.0"))
48         (if (ly:get-option 'strict-infinity-checking)
49             (exit 1))
50         "0.0")
51       (ly:number->string num)))
53 (define (number-pair->string4 numpair)
54   (ly:format "~4l" numpair)) 
56 ;;;
57 ;;; Lily output interface, PostScript implementation --- cleanup and docme
58 ;;;
60 ;; two beziers
61 (define (bezier-sandwich lst thick)
62   (ly:format "~l ~4f draw_bezier_sandwich" 
63              (map number-pair->string4 lst)
64           thick))
66 (define (char font i)
67   (ly:format "~a (\\~a) show"
68    (ps-font-command font)
69    (ly:inexact->string i 8)))
71 (define (circle radius thick fill)
72   (ly:format
73    "~a ~4f ~4f draw_circle"
74    (if fill
75      "true"
76      "false")
77    radius thick))
79 (define (dashed-line thick on off dx dy phase)
80   (ly:format "~4f ~4f ~4f [ ~4f ~4f ] ~4f draw_dashed_line"
81    dx
82    dy
83    thick
84    on
85    off
86    phase))
88 ;; what the heck is this interface ?
89 (define (dashed-slur thick on off l)
90   (ly:format "~l ~4f [ ~4f ~4f ] 0 draw_dashed_slur"
91           (let ((control-points (append (cddr l) (list (car l) (cadr l)))))
92             (map number-pair->string4 control-points))
93           thick
94           on
95           off))
97 (define (dot x y radius)
98   (ly:format " ~4l draw_dot" (list radius x y)))
100 (define (draw-line thick x1 y1 x2 y2)
101   (ly:format "~4f ~4f ~4f ~4f ~4f draw_line"
102           (- x2 x1) (- y2 y1)
103           x1 y1 thick))
105 (define (ellipse x-radius y-radius thick fill)
106   (ly:format
107    "~a ~4f ~4f ~4f draw_ellipse"
108    (if fill
109      "true"
110      "false")
111    x-radius y-radius thick))
113 (define (embedded-ps string)
114   string)
116 (define (glyph-string postscript-font-name
117                       size
118                       cid?
119                       w-x-y-named-glyphs)
121   (define (glyph-spec w x y g)
122     (let ((prefix (if (string? g) "/" "")))
123       (ly:format "~4f ~4f ~4f ~a~a"
124                  w x y
125                  prefix g)))
126   
127   (ly:format 
128    (if cid?
129 "/~a /CIDFont findresource ~a output-scale div scalefont setfont
131 ~a print_glyphs"
133 "/~a ~a output-scale div selectfont
135 ~a print_glyphs")
136           postscript-font-name
137           size
138           (string-join (map (lambda (x) (apply glyph-spec x))
139                             (reverse w-x-y-named-glyphs)) "\n")
140           (length w-x-y-named-glyphs)))
143 (define (grob-cause offset grob)
144   (if (ly:get-option 'point-and-click)
145       (let* ((cause (ly:grob-property grob 'cause))
146              (music-origin (if (ly:stream-event? cause)
147                                (ly:event-property cause 'origin))))
148         (if (ly:input-location? music-origin)
149             (let* ((location (ly:input-file-line-char-column music-origin))
150                    (raw-file (car location))
151                    (file (if (is-absolute? raw-file)
152                              raw-file
153                              (string-append (ly-getcwd) "/" raw-file)))
154                    (x-ext (ly:grob-extent grob grob X))
155                    (y-ext (ly:grob-extent grob grob Y)))
157               (if (and (< 0 (interval-length x-ext))
158                        (< 0 (interval-length y-ext)))
159                   (ly:format "~4f ~4f ~4f ~4f (textedit://~a:~a:~a:~a) mark_URI\n"
160                              (+ (car offset) (car x-ext))
161                              (+ (cdr offset) (car y-ext))
162                              (+ (car offset) (cdr x-ext))
163                              (+ (cdr offset) (cdr y-ext))
165                              ;; Backslashes are not valid
166                              ;; file URI path separators.
167                              (ly:string-percent-encode
168                                (ly:string-substitute "\\" "/" file))
170                              (cadr location)
171                              (caddr location)
172                              (cadddr location))
173                   ""))
174             ""))
175       ""))
177 (define (named-glyph font glyph)
178   (ly:format "~a /~a glyphshow " ;;Why is there a space at the end?
179              (ps-font-command font)
180              glyph))
182 (define (no-origin)
183   "")
185 (define (oval x-radius y-radius thick fill)
186   (ly:format
187    "~a ~4f ~4f ~4f draw_oval"
188    (if fill
189      "true"
190      "false")
191    x-radius y-radius thick))
193 (define (placebox x y s) 
194   (if (not (string-null? s))
195       (ly:format "~4f ~4f moveto ~a\n" x y s)
196       ""))
198 (define (polygon points blot-diameter filled?)
199   (ly:format "~a ~4l ~a ~4f draw_polygon"
200              (if filled? "true" "false")
201              points
202              (- (/ (length points) 2) 1)
203              blot-diameter))
205 (define (repeat-slash width slope beam-thickness)
206   (define (euclidean-length x y)
207     (sqrt (+ (* x x) (* y y))))
209   (let ((x-width (euclidean-length beam-thickness (/ beam-thickness slope)))
210         (height (* width slope)))
211     (ly:format "~4l draw_repeat_slash"
212              (list x-width width height))))
215 (define (round-filled-box left right bottom top blotdiam)
216   (let* ((halfblot (/ blotdiam 2))
217          (x (- halfblot left))
218          (width (- right (+ halfblot x)))
219          (y (- halfblot bottom))
220          (height (- top (+ halfblot y))))
221     (ly:format  "~4l draw_round_box"
222                 (list width height x y blotdiam))))
224 ;; save current color on stack and set new color
225 (define (setcolor r g b)
226   (ly:format "gsave ~4l setrgbcolor\n"
227               (list r g b)))
229 ;; restore color from stack
230 (define (resetcolor) "grestore\n")
232 ;; rotation around given point
233 (define (setrotation ang x y)
234   (ly:format "gsave ~4l translate ~a rotate ~4l translate\n"
235              (list x y)
236              ang
237              (list (* -1 x) (* -1 y))))
239 (define (resetrotation ang x y)
240   "grestore  ")
242 (define (unknown) 
243   "\n unknown\n")
245 (define (url-link url x y)
246   (ly:format "~a ~a currentpoint vector_add  ~a ~a currentpoint vector_add (~a) mark_URI"
247              (car x)
248              (car y)
249              (cdr x)
250              (cdr y)
251              url))
253 (define (path thickness exps)
254   (define (convert-path-exps exps)
255     (if (pair? exps)
256         (let*
257             ((head (car exps))
258              (rest (cdr exps))
259              (arity 
260               (cond
261                ((memq head '(rmoveto rlineto lineto moveto)) 2)
262                ((memq head '(rcurveto curveto)) 6)
263                ((eq? head 'closepath) 0)
264                (else 1)))
265              (args (take rest arity))
266              )
268           ;; WARNING: this is a vulnerability: a user can output arbitrary PS code here.
269           (cons (ly:format
270                         "~l ~a "
271                         args 
272                         head)
273                 (convert-path-exps (drop rest arity))))
274         '()))
275     
276     
277   (ly:format
278    "gsave currentpoint translate 1 setlinecap ~a setlinewidth\n~l stroke grestore"
279    thickness
280    (convert-path-exps exps)))
281