]> git.donarmstrong.com Git - lilypond.git/blob - scm/output-ps.scm
Fix #887: Use ly:string-percent-encode for textedit URIs.
[lilypond.git] / scm / output-ps.scm
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/>.
18
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
26
27 (define-module (scm output-ps)
28   #:re-export (quote))
29
30 (use-modules (guile)
31              (ice-9 regex)
32              (srfi srfi-1)
33              (srfi srfi-13)
34              (scm framework-ps)
35              (lily))
36
37 ;;; helper functions, not part of output interface
38 ;;;
39
40
41 ;; ice-9 format uses a lot of memory
42 ;; using simple-format almost halves lilypond cell usage
43
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)))
52
53 (define (number-pair->string4 numpair)
54   (ly:format "~4l" numpair)) 
55
56 ;;;
57 ;;; Lily output interface, PostScript implementation --- cleanup and docme
58 ;;;
59
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))
65
66 (define (char font i)
67   (ly:format "~a (\\~a) show"
68    (ps-font-command font)
69    (ly:inexact->string i 8)))
70
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))
78
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))
87
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))
96
97 (define (dot x y radius)
98   (ly:format " ~4l draw_dot" (list radius x y)))
99
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))
104
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))
112
113 (define (embedded-ps string)
114   string)
115
116 (define (glyph-string postscript-font-name
117                       size
118                       cid?
119                       w-x-y-named-glyphs)
120
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
130 ~a
131 ~a print_glyphs"
132
133 "/~a ~a output-scale div selectfont
134 ~a
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)))
141
142
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)))
156
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))
164
165                              ;; Backslashes are not valid
166                              ;; file URI path separators.
167                              (ly:string-substitute
168                                "\\" "/" (ly:string-percent-encode file))
169
170                              (cadr location)
171                              (caddr location)
172                              (cadddr location))
173                   ""))
174             ""))
175       ""))
176
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))
181
182 (define (no-origin)
183   "")
184
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))
192
193 (define (placebox x y s) 
194   (if (not (string-null? s))
195       (ly:format "~4f ~4f moveto ~a\n" x y s)
196       ""))
197
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))
204
205 (define (repeat-slash width slope beam-thickness)
206   (define (euclidean-length x y)
207     (sqrt (+ (* x x) (* y y))))
208
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))))
213
214
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))))
223
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)))
228
229 ;; restore color from stack
230 (define (resetcolor) "grestore\n")
231
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))))
238
239 (define (resetrotation ang x y)
240   "grestore  ")
241
242
243 (define (text font s)
244   ;; (ly:warning (_ "TEXT backend-command encountered in Pango backend"))
245   ;; (ly:warning (_ "Arguments: ~a ~a"" font str))
246   
247   (let* ((space-length (cdar (ly:text-dimension font " ")))
248          (space-move (string-append (number->string space-length)
249                                     ;; how much precision do we need here?
250                                     " 0.0 rmoveto "))
251          (out-vec (decode-byte-string s)))
252
253     (string-append
254      (ps-font-command font) " "
255      (string-join
256       (vector->list
257        (vector-for-each
258         
259         (lambda (sym)
260           (if (eq? sym 'space)
261               space-move
262               (string-append "/" (symbol->string sym) " glyphshow")))
263         out-vec))))))
264
265 (define (unknown) 
266   "\n unknown\n")
267
268 (define (url-link url x y)
269   (ly:format "~a ~a currentpoint vector_add  ~a ~a currentpoint vector_add (~a) mark_URI"
270              (car x)
271              (car y)
272              (cdr x)
273              (cdr y)
274              url))
275
276 (define (path thickness exps)
277   (define (convert-path-exps exps)
278     (if (pair? exps)
279         (let*
280             ((head (car exps))
281              (rest (cdr exps))
282              (arity 
283               (cond
284                ((memq head '(rmoveto rlineto lineto moveto)) 2)
285                ((memq head '(rcurveto curveto)) 6)
286                ((eq? head 'closepath) 0)
287                (else 1)))
288              (args (take rest arity))
289              )
290
291           ;; WARNING: this is a vulnerability: a user can output arbitrary PS code here.
292           (cons (ly:format
293                         "~l ~a "
294                         args 
295                         head)
296                 (convert-path-exps (drop rest arity))))
297         '()))
298     
299     
300   (ly:format
301    "gsave currentpoint translate 1 setlinecap ~a setlinewidth\n~l stroke grestore"
302    thickness
303    (convert-path-exps exps)))
304