]> git.donarmstrong.com Git - lilypond.git/blob - scm/framework-ps.scm
7486d5f64c32d8e10d747cef728f43f4d4562430
[lilypond.git] / scm / framework-ps.scm
1 ;;;; framework-ps.scm -- structure for PostScript output
2 ;;;;
3 ;;;;  source file of the GNU LilyPond music typesetter
4 ;;;;
5 ;;;; (c) 2004--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
6
7 (define-module (scm framework-ps))
8
9 ;;; this is still too big a mess.
10
11 (use-modules (ice-9 string-fun)
12              (guile)
13              (scm page)
14              (scm paper-system)
15              (srfi srfi-1)
16              (srfi srfi-13)
17              (scm clip-region)
18              (lily))
19
20 (define format ergonomic-simple-format)
21
22 (define framework-ps-module (current-module))
23
24 ;;(define pdebug stderr)
25 (define (pdebug . rest) #f)
26
27 (define-public (ps-font-command font)
28   (let* ((name (ly:font-file-name font))
29          (magnify (ly:font-magnification font)))
30
31     (string-append
32      "magfont"
33      (ly:string-substitute
34       " " "_"
35       (ly:string-substitute
36        "/" "_"
37        (ly:string-substitute
38         "%" "_" name)))
39      "m" (string-encode-integer (inexact->exact (round (* 1000 magnify)))))))
40
41 (define (tex-font? fontname)
42   (or
43    (equal? (substring fontname 0 2) "cm")
44    (equal? (substring fontname 0 2) "ec")))
45
46 (define (define-fonts paper)
47   (define font-list (ly:paper-fonts paper))
48   (define (define-font command fontname scaling)
49     (string-append
50       "/" command " { /" fontname " " (ly:number->string scaling) " output-scale div selectfont } bind def\n"))
51
52   (define (font-load-command font)
53     (let* ((specced-font-name (ly:font-name font))
54            (fontname (if specced-font-name
55                           specced-font-name
56                          (ly:font-file-name font)))
57            (command (ps-font-command font))
58
59            ;; FIXME -- see (ps-font-command )
60            (plain (ps-font-command font))
61            (designsize (ly:font-design-size font))
62            (magnification (* (ly:font-magnification font)))
63            (ops (ly:output-def-lookup paper 'output-scale))
64            (scaling (* ops magnification designsize)))
65
66       (if (equal? fontname "unknown")
67           (display (list font fontname)))
68       (define-font plain fontname scaling)))
69
70   (apply string-append
71          (map (lambda (x) (font-load-command x))
72               (filter (lambda (x) (not (ly:pango-font? x)))
73                       font-list))))
74
75 ;; FIXME: duplicated in other output backends
76 ;; FIXME: silly interface name
77 (define (output-variables layout)
78   ;; FIXME: duplicates output-layout's scope-entry->string, mostly
79   (define (value->string val)
80     (cond
81      ((string? val) (string-append "(" val ")"))
82      ((symbol? val) (symbol->string val))
83      ((number? val) (number->string val))
84      (else "")))
85
86   (define (output-entry ps-key ly-key)
87     (string-append
88      "/" ps-key " "
89      (value->string (ly:output-def-lookup layout ly-key)) " def\n"))
90
91   (string-append
92    "/lily-output-units "
93      (number->string (/ (ly:bp 1)))
94      " def %% millimeter\n"
95    (output-entry "staff-line-thickness" 'line-thickness)
96    (output-entry "line-width" 'line-width)
97    (output-entry "paper-size" 'papersizename)
98    (output-entry "staff-height" 'staff-height)  ;junkme.
99    "/output-scale "
100      (number->string (ly:output-def-lookup layout 'output-scale))
101      " def\n"
102    (output-entry "page-height" 'paper-height)
103    (output-entry "page-width" 'paper-width)))
104
105 (define (dump-page outputter page page-number page-count landscape?)
106   (ly:outputter-dump-string
107    outputter
108    (string-append
109     (format "%%Page: ~a ~a\n" page-number page-number)
110     "%%BeginPageSetup\n"
111     (if landscape?
112         "page-width output-scale lily-output-units mul mul 0 translate 90 rotate\n"
113         "")
114     "%%EndPageSetup\n"
115     
116     "true setstrokeadjust\n"
117     "gsave 0 paper-height translate "
118     "set-ps-scale-to-lily-scale "
119     "\n"))
120   (ly:outputter-dump-stencil outputter page)
121   (ly:outputter-dump-string outputter "stroke grestore\nshowpage\n"))
122
123 (define (supplies-or-needs paper load-fonts?)
124   (define (extract-names font)
125     (if (ly:pango-font? font)
126         (map car (ly:pango-font-physical-fonts font))
127         (list  (ly:font-name font))))
128
129   (let* ((fonts (ly:paper-fonts paper))
130          (names (apply append (map extract-names fonts))))
131
132     (apply string-append
133            (map (lambda (f)
134                   (format
135                    (if load-fonts?
136                     "%%DocumentSuppliedResources: font ~a\n"
137                     "%%DocumentNeededResources: font ~a\n")
138                    f))
139                 (uniq-list (sort names string<?))))))
140
141 (define (eps-header paper bbox load-fonts?)
142   (string-append "%!PS-Adobe-2.0 EPSF-2.0\n"
143                  "%%Creator: LilyPond "
144                  (lilypond-version)
145                  "\n"
146                  "%%BoundingBox: "
147                  (string-join (map ly:number->string bbox) " ") "\n"
148                  "%%Orientation: "
149                  (if (eq? (ly:output-def-lookup paper 'landscape) #t)
150                      "Landscape\n"
151                      "Portrait\n")
152                  (supplies-or-needs paper load-fonts?)
153                  "%%EndComments\n"))
154
155 (define (ps-document-media paper) 
156  (let* ((w (/ (*
157                (ly:output-def-lookup paper 'output-scale)
158                (ly:output-def-lookup paper 'paper-width)) (ly:bp 1)))
159         (h (/ (*
160                (ly:output-def-lookup paper 'paper-height)
161                (ly:output-def-lookup paper 'output-scale))
162             (ly:bp 1)))
163         (landscape? (eq? (ly:output-def-lookup paper 'landscape) #t)))
164   (ly:format "%%DocumentMedia: ~a ~2f ~2f ~a ~a ~a\n"
165              (ly:output-def-lookup paper 'papersizename)
166              (if landscape? h w)
167              (if landscape? w h)
168              80  ;; weight
169              "()" ;; color
170              "()"  ;; type
171   )))
172
173
174 (define (file-header paper page-count load-fonts?)
175   (string-append "%!PS-Adobe-3.0\n"
176                  "%%Creator: LilyPond "
177                  (lilypond-version)
178                  "\n"
179                  
180                  "%%Pages: " (number->string page-count) "\n"
181                  "%%PageOrder: Ascend\n"
182                  "%%Orientation: "
183                  (if (eq? (ly:output-def-lookup paper 'landscape) #t)
184                      "Landscape\n"
185                      "Portrait\n")
186                  (ps-document-media paper)
187                  (supplies-or-needs paper load-fonts?)
188                  "%%EndComments\n"))
189
190 (define (procset file-name)
191   (format
192     "%%BeginResource: procset (~a) 1 0
193 ~a
194 %%EndResource
195 "
196     file-name (cached-file-contents file-name)))
197
198 (define (embed-document file-name)
199   (format "%%BeginDocument: ~a
200 ~a
201 %%EndDocument
202
203     file-name (cached-file-contents file-name)))
204
205 (define (setup-variables paper)
206   (string-append
207    "\n"
208    (define-fonts paper)
209    (output-variables paper)
210    ))
211
212 (define (cff-font? font)
213   (let*
214       ((cff-string (ly:otf-font-table-data font "CFF ")))
215     (> (string-length cff-string) 0)))
216
217 (define-public (ps-embed-cff body font-set-name version)
218   (let* ((binary-data
219           (string-append
220            (format "/~a ~s StartData " font-set-name (string-length body))
221            body))
222
223          (header
224           (format
225            "%%BeginResource: font ~a
226 %!PS-Adobe-3.0 Resource-FontSet
227 %%DocumentNeededResources: ProcSet (FontSetInit)
228 %%Title: (FontSet/~a)
229 %%Version: ~s
230 %%EndComments
231 %%IncludeResource: ProcSet (FontSetInit)
232 %%BeginResource: FontSet (~a)
233 /FontSetInit /ProcSet findresource begin
234 %%BeginData: ~s Binary Bytes
235 "
236            font-set-name font-set-name version font-set-name
237            (string-length binary-data)))
238          (footer "\n%%EndData
239 %%EndResource
240 %%EndResource\n"))
241
242     (string-append
243      header
244      binary-data
245      footer)))
246
247
248 (define (write-preamble paper load-fonts? port)
249   (define (internal-font? file-name)
250     (or (string-startswith file-name "Emmentaler")
251         (string-startswith file-name "emmentaler")
252         (string-startswith file-name "aybabtu")
253         (string-startswith file-name "Aybabtu")))
254   (define (load-font-via-GS font-name-filename)       
255     (define (ps-load-file file-name)
256       (if (string? file-name)
257           (if (string-contains file-name (ly:get-option 'datadir))
258               (begin
259                 (set! file-name (ly:string-substitute (ly:get-option 'datadir) "" file-name))
260                 (format "lilypond-datadir (~a) concatstrings (r) file .loadfont" file-name))
261               
262               (format "(~a) (r) file .loadfont\n" file-name))
263           (format "% cannot find font file: ~a\n" file-name)))
264
265     (let* ((font (car font-name-filename))
266            (name (cadr font-name-filename))
267            (file-name (caddr font-name-filename))
268            (bare-file-name (ly:find-file file-name)))
269
270       (cons
271        name
272        
273        (if (mac-font? bare-file-name)
274            (handle-mac-font name bare-file-name)
275            (cond
276             ((internal-font? file-name)
277              (ps-load-file (ly:find-file
278                             (format "~a.otf"  file-name))))
279             ((string? bare-file-name)
280              (ps-load-file file-name))
281             (else
282              (ly:warning (_ "cannot embed ~S=~S") name file-name)
283              "")))
284
285           )))
286
287   (define (dir-join a b)
288     (if (equal? a "")
289         b
290         (string-append a "/" b)))
291     
292   (define (dir-listing dir-name)
293     (define (dir-helper dir lst)
294       (let ((e (readdir dir)))
295         (if (eof-object? e) lst (dir-helper dir (cons e lst)))))
296     (reverse (dir-helper (opendir dir-name) '())))
297       
298   (define (handle-mac-font name filename)
299     (let*
300         ((dir-name  (tmpnam))
301          (files '())
302          (status 0)
303          (embed #f))
304
305       (mkdir dir-name #o700)
306       (set! status (ly:system
307                     (format "cd ~a && fondu -force '~a'" dir-name filename)))
308       
309       (set! files (dir-listing dir-name))
310       
311       (for-each
312        (lambda (f)
313          (let*
314              ((full-name  (dir-join dir-name f)))
315            
316            (if (and (not embed)
317                     (equal? 'regular (stat:type (stat full-name)))
318                     (equal? name (ly:ttf-ps-name full-name)))
319                
320                (set! embed
321                      (font-file-as-ps-string name full-name)))
322            
323            (if (or (equal? "." f) 
324                    (equal? ".." f))
325                #t
326                (delete-file full-name))))
327
328
329        files)
330       (rmdir dir-name)
331
332       (if (not embed)
333           (begin
334             (set! embed "% failed\n")
335             (ly:warning (_ "cannot extract file matching ~a from ~a") name filename)))
336       embed))
337
338     (define (font-file-as-ps-string name file-name)
339       (let*
340           ((downcase-file-name (string-downcase file-name)))
341         
342       (cond
343        ((and file-name (string-endswith downcase-file-name ".pfa"))
344         (embed-document file-name))
345        ((and file-name (string-endswith downcase-file-name ".pfb"))
346         (ly:pfb->pfa file-name))
347        ((and file-name (string-endswith downcase-file-name ".ttf"))
348         (ly:ttf->pfa file-name))
349        ((and file-name (string-endswith downcase-file-name ".otf"))
350         (ps-embed-cff (ly:otf->cff file-name) name 0))
351        (else
352         (ly:warning (_ "do not know how to embed ~S=~S") name file-name)
353         ""))))
354
355     (define (mac-font? bare-file-name)
356       (and
357        (eq? PLATFORM 'darwin)
358        bare-file-name
359        (or
360         (string-endswith  bare-file-name ".dfont")
361         (= (stat:size (stat bare-file-name)) 0))))
362
363   (define (load-font font-name-filename)
364     (let* ((font (car font-name-filename))
365            (name (cadr font-name-filename))
366            (file-name (caddr font-name-filename))
367            (bare-file-name (ly:find-file file-name)))
368       
369       (cons
370        name
371        (cond
372
373         ((mac-font? bare-file-name)
374          (handle-mac-font name bare-file-name))
375
376         ((and font (cff-font? font))
377          (ps-embed-cff (ly:otf-font-table-data font "CFF ")
378                        name
379                        0))
380
381         (bare-file-name (font-file-as-ps-string name bare-file-name))
382         (else
383          (ly:warning (_ "do not know how to embed font ~s ~s ~s")
384                      name file-name font))))))
385         
386
387   (define (load-fonts paper)
388     (let* ((fonts (ly:paper-fonts paper))
389
390            ;; todo - doc format of list.
391            (all-font-names
392             (map
393              (lambda (font)
394                (cond
395                 ((string? (ly:font-file-name font))
396                  (list (list
397                         font
398                         (ly:font-name font)
399                         (ly:font-file-name font))))
400                 ((ly:pango-font? font)
401                  (map
402                   (lambda (name-psname-pair)
403                     (list #f
404                           (car name-psname-pair)
405                           (cdr name-psname-pair)))
406                   (ly:pango-font-physical-fonts font)))
407
408                 (else
409                  (ly:font-sub-fonts font))))
410
411              fonts))
412            (font-names
413             (uniq-list
414              (sort (apply append all-font-names)
415                    (lambda (x y) (string<? (cadr x) (cadr y))))))
416
417            ;; slightly spaghetti-ish: deciding what to load where
418            ;; is smeared out.
419            (font-loader (lambda (name)
420                           (cond
421                            ((ly:get-option 'gs-load-fonts) 
422                             (load-font-via-GS name))
423                            ((ly:get-option 'gs-load-lily-fonts)
424                             (if (or
425                                  (string-contains (caddr name) (ly:get-option 'datadir))
426                                  (internal-font? (caddr name)))
427
428                                 (load-font-via-GS name)
429                                 (load-font name)))
430                            (else (load-font name)))))
431                          
432            (pfas (map font-loader font-names)))
433       pfas))
434
435   (display "%%BeginProlog\n" port)
436
437   (format port
438             "/lilypond-datadir where {pop} {userdict /lilypond-datadir (~a) put } ifelse"
439             (ly:get-option 'datadir))
440   
441   (if load-fonts?
442       (for-each
443        (lambda (f)
444          (format port "\n%%BeginFont: ~a\n" (car f))
445          (display (cdr f) port)
446          (display "\n%%EndFont\n" port))
447        (load-fonts paper)))
448
449   (display (setup-variables paper) port)
450
451   ;; adobe note 5002: should initialize variables before loading routines.
452   (display (procset "music-drawing-routines.ps") port)
453   (display (procset "lilyponddefs.ps") port)
454
455   (display "%%EndProlog\n" port)
456   
457   (display "%%BeginSetup\ninit-lilypond-parameters\n%%EndSetup\n\n" port))
458
459 (define-public (output-framework basename book scopes fields)
460   (let* ((filename (format "~a.ps" basename))
461          (outputter (ly:make-paper-outputter
462                      ;; FIXME: better wrap open/open-file,
463                      ;; content-mangling is always bad.
464                      ;; MINGW hack: need to have "b"inary for embedding CFFs
465                      (open-file filename "wb")
466                      'ps))
467          (paper (ly:paper-book-paper book))
468          (systems (ly:paper-book-systems book))
469          (page-stencils (map page-stencil (ly:paper-book-pages book)))
470          
471          (landscape? (eq? (ly:output-def-lookup paper 'landscape) #t))
472          (page-number (1- (ly:output-def-lookup paper 'first-page-number)))
473          (page-count (length page-stencils))
474          (port (ly:outputter-port outputter)))
475
476
477     (if (ly:get-option 'clip-systems)
478         (clip-system-EPSes basename book))
479
480     (if (ly:get-option 'dump-signatures)
481         (write-system-signatures basename (ly:paper-book-systems book) 1))
482   
483     (output-scopes scopes fields basename)
484     (display (file-header paper page-count #t) port)
485     
486     ;; don't do BeginDefaults PageMedia: A4 
487     ;; not necessary and wrong
488     
489     (write-preamble paper #t port)
490
491     (for-each
492      (lambda (page)
493        (set! page-number (1+ page-number))
494        (dump-page outputter page page-number page-count landscape?))
495      page-stencils)
496
497     (display "%%Trailer\n%%EOF\n" port)
498     (ly:outputter-close outputter)
499     (postprocess-output book framework-ps-module filename
500                          (ly:output-formats))))
501
502 (define-public (dump-stencil-as-EPS paper dump-me filename
503                                     load-fonts)
504   
505   (let*
506       ((xext (ly:stencil-extent dump-me X))
507        (yext (ly:stencil-extent dump-me Y))
508        (padding (ly:get-option 'eps-box-padding))
509        (left-overshoot (if (number? padding)
510                            (* -1 padding (ly:output-def-lookup paper 'mm))
511                            #f))
512        (bbox
513         (map
514          (lambda (x)
515            (if (or (nan? x) (inf? x)
516                      ;; FIXME: huh?
517                    (equal? (format #f "~S" x) "+#.#")
518                    (equal? (format #f "~S" x) "-#.#"))
519                0.0 x))
520
521            ;; the left-overshoot is to make sure that
522            ;; bar numbers  stick out of margin uniformly.
523            ;;
524            (list
525             
526             (if (number? left-overshoot)
527                 (min left-overshoot (car xext))
528                 (car xext))
529             (car yext) (cdr xext) (cdr yext)))))
530
531        (dump-stencil-as-EPS-with-bbox paper dump-me filename load-fonts bbox)
532        ))
533          
534            
535 (define-public (dump-stencil-as-EPS-with-bbox paper dump-me filename
536                                               load-fonts
537                                               bbox)
538   "Create an EPS file from stencil DUMP-ME to FILENAME. BBOX has format
539    (left-x, lower-y, right x, up-y).  If LOAD-FONTS set, include fonts inline." 
540
541   (define (to-rounded-bp-box box)
542     "Convert box to 1/72 inch with rounding to enlarge the box."
543     (let* ((scale (ly:output-def-lookup paper 'output-scale))
544            (strip-non-number (lambda (x)
545                                (if (or (nan? x) (inf? x)) 0.0 x)))
546            (directed-round (lambda (x rounder)
547                              (inexact->exact
548                               (rounder (/ (* (strip-non-number x) scale)
549                                           (ly:bp 1)))))))
550       (list (directed-round (car box) floor)
551             (directed-round (cadr box) floor)
552             (directed-round (max (1+ (car box)) (caddr box)) ceiling)
553             (directed-round (max (1+ (cadr box)) (cadddr box)) ceiling)
554           )))
555
556   (let* ((outputter (ly:make-paper-outputter
557                      ;; FIXME: better wrap open/open-file,
558                      ;; content-mangling is always bad.
559                      ;; MINGW hack: need to have "b"inary for embedding CFFs
560                      (open-file (format "~a.eps" filename) "wb")
561                      'ps))
562
563          (port (ly:outputter-port outputter))
564          (rounded-bbox (to-rounded-bp-box bbox))
565          (port (ly:outputter-port outputter))
566          (header (eps-header paper rounded-bbox load-fonts)))
567
568     (display header port)
569     (write-preamble paper load-fonts port)
570     (display "gsave set-ps-scale-to-lily-scale\n" port)
571     (ly:outputter-dump-stencil outputter dump-me)
572     (display "stroke grestore\n%%Trailer\n%%EOF\n" port)
573     (ly:outputter-close outputter)))
574
575
576
577 (define (clip-systems-to-region
578          basename paper systems region
579          do-pdf)
580
581   (let*
582       ((extents-system-pairs
583         (filtered-map
584          (lambda (paper-system)
585            (let*
586                ((x-ext (system-clipped-x-extent
587                         (paper-system-system-grob paper-system)
588                         region)))
589
590              (if x-ext
591                  (cons x-ext paper-system)
592                  #f)))
593          
594          systems))
595        (count 0))
596     
597     (for-each
598      (lambda (ext-system-pair)
599        (let*
600            ((xext (car ext-system-pair))
601             (paper-system (cdr ext-system-pair))
602             (yext (paper-system-extent paper-system Y))
603             (bbox (list (car xext) (car yext)
604                         (cdr xext) (cdr yext)))
605             (filename (if (< 0 count)
606                           (format "~a-~a" basename count)
607                           basename)))
608
609          (set! count (1+ count))
610          (dump-stencil-as-EPS-with-bbox
611           paper
612           (paper-system-stencil paper-system)
613           filename
614           (ly:get-option 'include-eps-fonts)
615           bbox)
616
617          (if do-pdf
618              (postscript->pdf  0 0  (format "~a.eps" filename)))
619          ))
620
621      extents-system-pairs)
622     ))
623
624
625 (define-public (clip-system-EPSes basename paper-book)
626   (define do-pdf (member  "pdf" (ly:output-formats)))
627
628   (define (clip-score-systems basename systems)
629     (let*
630         ((layout (ly:grob-layout (paper-system-system-grob (car systems))))
631          (regions (ly:output-def-lookup layout 'clip-regions)))
632       
633       (for-each
634        (lambda (region)
635          (clip-systems-to-region
636           (format "~a-from-~a-to-~a-clip"
637                   basename
638                   (rhythmic-location->file-string (car region))
639                   (rhythmic-location->file-string (cdr region)))
640           layout systems region
641           do-pdf))
642        
643        regions)))
644   
645
646   ;; partition in system lists sharing their layout blocks
647   (let*
648       ((systems (ly:paper-book-systems paper-book))
649        (count 0)
650        (score-system-list '()))
651
652     (fold 
653      (lambda (system last-system)
654     
655        
656        (if (not (and last-system
657                      (equal? (paper-system-layout last-system)
658                              (paper-system-layout system))))
659            (set! score-system-list (cons '() score-system-list)))
660        
661        (if (paper-system-layout system)
662            (set-car! score-system-list (cons system (car score-system-list))))
663
664        ;; pass value.
665        system)
666
667      #f 
668      systems)
669
670     (for-each
671      (lambda (system-list)
672        (clip-score-systems
673         (if (> count 0)
674             (format "~a-~a" basename count)
675             basename)
676         system-list))
677
678      score-system-list)))
679
680
681 (define-public (output-preview-framework basename book scopes fields)
682   (let* ((paper (ly:paper-book-paper book))
683          (systems (ly:paper-book-systems book))
684          (scale (ly:output-def-lookup paper 'output-scale))
685          (to-dump-systems '()))
686
687     ;; skip booktitles.
688     (if (and
689          (not (ly:get-option 'include-book-title-preview))
690          (pair? systems)
691          (ly:prob-property (car systems) 'is-book-title #f))
692
693         (set! systems (cdr systems)))
694
695     (for-each
696      (lambda (sys)
697        (if (or
698             (paper-system-title? sys)
699             (not (pair? to-dump-systems))
700             (paper-system-title? (car to-dump-systems)))
701            (set! to-dump-systems (cons sys to-dump-systems))))
702      systems)
703
704     (dump-stencil-as-EPS
705      paper
706      (stack-stencils Y DOWN 0.0
707                      (map paper-system-stencil (reverse to-dump-systems)))
708      (format "~a.preview" basename)
709      #t)
710
711     (postprocess-output book framework-ps-module
712                         (format "~a.preview.eps" basename)
713                         (cons "png" (ly:output-formats)))))
714
715 (if #f
716     (define-public (output-preview-framework basename book scopes fields)
717
718       (let* ((paper (ly:paper-book-paper book))
719              (systems (ly:paper-book-systems book))
720              (scale (ly:output-def-lookup paper 'output-scale))
721              (titles (take-while paper-system-title? systems))
722              (non-title (find (lambda (x)
723                                 (not (paper-system-title? x))) systems))
724              (dump-me
725               (stack-stencils Y DOWN 0.0
726                               (map paper-system-stencil
727                                    (append titles (list non-title))))))
728         (output-scopes scopes fields basename)
729         (dump-stencil-as-EPS paper dump-me
730                              (format "~a.preview" basename)
731                              #t)
732
733         (postprocess-output book framework-ps-module
734                             (format "~a.preview.eps" basename)
735                              (ly:output-formats)))))
736
737 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
738
739 (define-public (convert-to-pdf book name)
740   (let* ((defs (ly:paper-book-paper book))
741          (landscape (ly:output-def-lookup defs 'landscape))
742          (output-scale (ly:output-def-lookup defs 'output-scale))
743          (convert (lambda (x) (* x output-scale (/ (ly:bp 1)))))
744          
745          (paper-width (convert (ly:output-def-lookup defs 'paper-width)))
746          (paper-height (convert (ly:output-def-lookup defs 'paper-height)))
747
748          (w (if landscape paper-height paper-width))
749          (h (if landscape paper-width paper-height))
750          )
751
752     (if (equal? (basename name ".ps") "-")
753         (ly:warning (_ "cannot convert <stdout> to ~S" "PDF"))
754         (postscript->pdf w h name))))
755
756 (define-public (convert-to-png book name)
757   (let* ((defs (ly:paper-book-paper book))
758          (defs-resolution (ly:output-def-lookup defs 'pngresolution))
759          (resolution (if (number? defs-resolution)
760                          defs-resolution
761                          (ly:get-option 'resolution)))
762          (paper-width (ly:output-def-lookup defs 'paper-width))
763          (paper-height (ly:output-def-lookup defs 'paper-height))
764          (output-scale (ly:output-def-lookup defs 'output-scale)))
765
766     (postscript->png resolution
767                      (* paper-width output-scale (/ (ly:bp 1)))
768                      (* paper-height output-scale (/ (ly:bp 1)))
769                      name)))
770
771 (define-public (convert-to-dvi book name)
772   (ly:warning (_ "cannot generate ~S using the postscript back-end") "DVI"))
773
774 (define-public (convert-to-tex book name)
775   (ly:warning (_ "cannot generate ~S using the postscript back-end") "TeX"))
776
777 (define-public (convert-to-ps book name)
778   #t)
779
780 (define-public (output-classic-framework basename book scopes fields)
781
782   (ly:error (_ "\nThe PostScript backend does not support the system-by-system 
783 output. For that, use the EPS backend instead,
784
785   lilypond -dbackend=eps FILE
786
787 If have cut & pasted a lilypond fragment from a webpage, be sure
788 to only remove anything before
789
790   %% ****************************************************************
791   %% Start cut-&-pastable-section
792   %% ****************************************************************
793 ")))