]> git.donarmstrong.com Git - lilypond.git/blob - scm/framework-ps.scm
Merge commit 'ded1396' into jneeman
[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--2006 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
250   (define (load-font-via-GS font-name-filename)
251     (define (ps-load-file file-name)
252       (if (string? file-name)
253           (if (string-contains file-name (ly:get-option 'datadir))
254               (begin
255                 (set! file-name (ly:string-substitute (ly:get-option 'datadir) "" file-name))
256                 (format "lilypond-datadir (~a) concatstrings (r) file .loadfont" file-name))
257               (format "(~a) (r) file .loadfont\n" file-name))
258           (format "% cannot find font file: ~a\n" file-name)))
259
260     (let* ((font (car font-name-filename))
261            (name (cadr font-name-filename))
262            (file-name (caddr font-name-filename))
263            (bare-file-name (ly:find-file file-name)))
264
265       (cons
266        name
267        
268        (if (mac-font? bare-file-name)
269            (handle-mac-font name bare-file-name)
270            (cond
271             ((or (string-startswith file-name "Emmentaler")
272                  (string-startswith file-name "emmentaler")
273                  (string-startswith file-name "aybabtu")
274                  (string-startswith file-name "Aybabtu"))
275              (ps-load-file (ly:find-file
276                             (format "~a.otf"  file-name))))
277             ((string? bare-file-name)
278              (ps-load-file file-name))
279             (else
280              (ly:warning (_ "cannot embed ~S=~S") name file-name)
281              "")))
282
283           )))
284
285   (define (dir-join a b)
286     (if (equal? a "")
287         b
288         (string-append a "/" b)))
289     
290   (define (dir-listing dir-name)
291     (define (dir-helper dir lst)
292       (let ((e (readdir dir)))
293         (if (eof-object? e) lst (dir-helper dir (cons e lst)))))
294     (reverse (dir-helper (opendir dir-name) '())))
295       
296   (define (handle-mac-font name filename)
297     (let*
298         ((dir-name  (tmpnam))
299          (files '())
300          (status 0)
301          (embed #f))
302
303       (mkdir dir-name #o700)
304       (set! status (ly:system
305                     (format "cd ~a && fondu -force '~a'" dir-name filename)))
306       
307       (set! files (dir-listing dir-name))
308       
309       (for-each
310        (lambda (f)
311          (let*
312              ((full-name  (dir-join dir-name f)))
313            
314            (if (and (not embed)
315                     (equal? 'regular (stat:type (stat full-name)))
316                     (equal? name (ly:ttf-ps-name full-name)))
317                
318                (set! embed
319                      (font-file-as-ps-string name full-name)))
320            
321            (if (or (equal? "." f) 
322                    (equal? ".." f))
323                #t
324                (delete-file full-name))))
325
326
327        files)
328       (rmdir dir-name)
329
330       (if (not embed)
331           (begin
332             (set! embed "% failed \n")
333             (ly:warning (_ "cannot extract file matching ~a from ~a") name filename)))
334       embed))
335
336     (define (font-file-as-ps-string name file-name)
337       (let*
338           ((downcase-file-name (string-downcase file-name)))
339         
340       (cond
341        ((and file-name (string-endswith downcase-file-name ".pfa"))
342         (embed-document file-name))
343        ((and file-name (string-endswith downcase-file-name ".pfb"))
344         (ly:pfb->pfa file-name))
345        ((and file-name (string-endswith downcase-file-name ".ttf"))
346         (ly:ttf->pfa file-name))
347        ((and file-name (string-endswith downcase-file-name ".otf"))
348         (ps-embed-cff (ly:otf->cff file-name) name 0))
349        (else
350         (ly:warning (_ "do not know how to embed ~S=~S") name file-name)
351         ""))))
352
353     (define (mac-font? bare-file-name)
354       (and
355        (eq? PLATFORM 'darwin)
356        bare-file-name
357        (or
358         (string-endswith  bare-file-name ".dfont")
359         (= (stat:size (stat bare-file-name)) 0))))
360
361   (define (load-font font-name-filename)
362     (let* ((font (car font-name-filename))
363            (name (cadr font-name-filename))
364            (file-name (caddr font-name-filename))
365            (bare-file-name (ly:find-file file-name)))
366       
367       (cons
368        name
369        (cond
370
371         ((mac-font? bare-file-name)
372          (handle-mac-font name bare-file-name))
373
374         ((and font (cff-font? font))
375          (ps-embed-cff (ly:otf-font-table-data font "CFF ")
376                        name
377                        0))
378
379         (bare-file-name (font-file-as-ps-string name bare-file-name))
380         (else
381          (ly:warning (_ "do not know how to embed font ~s ~s ~s")
382                      name file-name font))))))
383         
384
385   (define (load-fonts paper)
386     (let* ((fonts (ly:paper-fonts paper))
387            (all-font-names
388             (map
389              (lambda (font)
390                (cond
391                 ((string? (ly:font-file-name font))
392                  (list (list
393                         font
394                         (ly:font-name font)
395                         (ly:font-file-name font))))
396                 ((ly:pango-font? font)
397                  (map
398                   (lambda (name-psname-pair)
399                     (list #f
400                           (car name-psname-pair)
401                           (cdr name-psname-pair)))
402                   (ly:pango-font-physical-fonts font)))
403
404                 (else
405                  (ly:font-sub-fonts font))))
406
407              fonts))
408            (font-names
409             (uniq-list
410              (sort (apply append all-font-names)
411                    (lambda (x y) (string<? (cadr x) (cadr y))))))
412
413            (font-loader (if (ly:get-option 'gs-load-fonts)
414                             load-font-via-GS
415                             load-font))
416                          
417            (pfas (map font-loader font-names)))
418       pfas))
419
420   (display "%%BeginProlog\n" port)
421
422   (format port
423             "/lilypond-datadir where {pop} {userdict /lilypond-datadir (~a) put } ifelse"
424             (ly:get-option 'datadir))
425   
426   (if load-fonts?
427       (for-each
428        (lambda (f)
429          (format port "\n%%BeginFont: ~a\n" (car f))
430          (display (cdr f) port)
431          (display "\n%%EndFont\n" port))
432        (load-fonts paper)))
433
434   (display (setup-variables paper) port)
435
436   ;; adobe note 5002: should initialize variables before loading routines.
437   (display (procset "music-drawing-routines.ps") port)
438   (display (procset "lilyponddefs.ps") port)
439
440   (display "%%EndProlog\n" port)
441   
442   (display "%%BeginSetup\ninit-lilypond-parameters\n%%EndSetup\n\n" port))
443
444 (define-public (output-framework basename book scopes fields)
445   (let* ((filename (format "~a.ps" basename))
446          (outputter (ly:make-paper-outputter
447                      ;; FIXME: better wrap open/open-file,
448                      ;; content-mangling is always bad.
449                      ;; MINGW hack: need to have "b"inary for embedding CFFs
450                      (open-file filename "wb")
451                      'ps))
452          (paper (ly:paper-book-paper book))
453          (systems (ly:paper-book-systems book))
454          (page-stencils (map page-stencil (ly:paper-book-pages book)))
455          
456          (landscape? (eq? (ly:output-def-lookup paper 'landscape) #t))
457          (page-number (1- (ly:output-def-lookup paper 'first-page-number)))
458          (page-count (length page-stencils))
459          (port (ly:outputter-port outputter)))
460
461
462     (if (ly:get-option 'clip-systems)
463         (clip-system-EPSes basename book))
464
465     (if (ly:get-option 'dump-signatures)
466         (write-system-signatures basename (ly:paper-book-systems book) 1))
467   
468     (output-scopes scopes fields basename)
469     (display (file-header paper page-count #t) port)
470     
471     ;; don't do BeginDefaults PageMedia: A4 
472     ;; not necessary and wrong
473     
474     (write-preamble paper #t port)
475
476     (for-each
477      (lambda (page)
478        (set! page-number (1+ page-number))
479        (dump-page outputter page page-number page-count landscape?))
480      page-stencils)
481
482     (display "%%Trailer\n%%EOF\n" port)
483     (ly:outputter-close outputter)
484     (postprocess-output book framework-ps-module filename
485                          (ly:output-formats))))
486
487 (define-public (dump-stencil-as-EPS paper dump-me filename
488                                     load-fonts)
489   
490   (let*
491       ((xext (ly:stencil-extent dump-me X))
492        (yext (ly:stencil-extent dump-me Y))
493        (padding (ly:get-option 'eps-box-padding))
494        (left-overshoot (if (number? padding)
495                            (* -1 padding (ly:output-def-lookup paper 'mm))
496                            #f))
497        (bbox
498         (map
499          (lambda (x)
500            (if (or (nan? x) (inf? x)
501                      ;; FIXME: huh?
502                    (equal? (format #f "~S" x) "+#.#")
503                    (equal? (format #f "~S" x) "-#.#"))
504                0.0 x))
505
506            ;; the left-overshoot is to make sure that
507            ;; bar numbers  stick out of margin uniformly.
508            ;;
509            (list
510             
511             (if (number? left-overshoot)
512                 (min left-overshoot (car xext))
513                 (car xext))
514             (car yext) (cdr xext) (cdr yext)))))
515
516        (dump-stencil-as-EPS-with-bbox paper dump-me filename load-fonts bbox)
517        ))
518          
519            
520 (define-public (dump-stencil-as-EPS-with-bbox paper dump-me filename
521                                               load-fonts
522                                               bbox)
523   (define (to-bp-box mmbox)
524     (let* ((scale (ly:output-def-lookup paper 'output-scale))
525            (box (map
526                  (lambda (x)
527                    (if (or (nan? x) (inf? x))
528                        0
529                        (inexact->exact
530                         (round (/ (* x scale) (ly:bp 1)))))) mmbox)))
531       
532     (list (car box)
533           (cadr box)
534           (max (1+ (car box)) (caddr box))
535           (max (1+ (cadr box)) (cadddr box))
536           )))
537
538   (let* ((outputter (ly:make-paper-outputter
539                      ;; FIXME: better wrap open/open-file,
540                      ;; content-mangling is always bad.
541                      ;; MINGW hack: need to have "b"inary for embedding CFFs
542                      (open-file (format "~a.eps" filename) "wb")
543                      'ps))
544
545          (port (ly:outputter-port outputter))
546          (rounded-bbox (to-bp-box bbox))
547          (port (ly:outputter-port outputter))
548          (header (eps-header paper rounded-bbox load-fonts)))
549
550     (display header port)
551     (write-preamble paper load-fonts port)
552     (display "gsave set-ps-scale-to-lily-scale \n" port)
553     (ly:outputter-dump-stencil outputter dump-me)
554     (display "stroke grestore\n%%Trailer\n%%EOF\n" port)
555     (ly:outputter-close outputter)))
556
557
558
559 (define (clip-systems-to-region
560          basename paper systems region
561          do-pdf)
562
563   (let*
564       ((extents-system-pairs
565         (filtered-map
566          (lambda (paper-system)
567            (let*
568                ((x-ext (system-clipped-x-extent
569                         (paper-system-system-grob paper-system)
570                         region)))
571
572              (if x-ext
573                  (cons x-ext paper-system)
574                  #f)))
575          
576          systems))
577        (count 0))
578     
579     (for-each
580      (lambda (ext-system-pair)
581        (let*
582            ((xext (car ext-system-pair))
583             (paper-system (cdr ext-system-pair))
584             (yext (paper-system-extent paper-system Y))
585             (bbox (list (car  xext) (car yext)
586                         (cdr xext) (cdr yext)))
587             (filename (if (< 0 count)
588                           (format "~a-~a" basename count)
589                           basename)))
590
591          (set! count (1+ count))
592          (dump-stencil-as-EPS-with-bbox
593           paper
594           (paper-system-stencil paper-system)
595           filename
596           (ly:get-option 'include-eps-fonts)
597           bbox)
598
599          (if do-pdf
600              (postscript->pdf  0 0  (format "~a.eps" filename)))
601          ))
602
603      extents-system-pairs)
604     ))
605
606
607 (define-public (clip-system-EPSes basename paper-book)
608   (define do-pdf (member  "pdf" (ly:output-formats)))
609
610   (define (clip-score-systems basename systems)
611     (let*
612         ((layout (ly:grob-layout (paper-system-system-grob (car systems))))
613          (regions (ly:output-def-lookup layout 'clip-regions)))
614       
615       (for-each
616        (lambda (region)
617          (clip-systems-to-region
618           (format "~a-from-~a-to-~a-clip"
619                   basename
620                   (rhythmic-location->file-string (car region))
621                   (rhythmic-location->file-string (cdr region)))
622           layout systems region
623           do-pdf))
624        
625        regions)))
626   
627
628   ;; partition in system lists sharing their layout blocks
629   (let*
630       ((systems (ly:paper-book-systems paper-book))
631        (count 0)
632        (score-system-list '()))
633
634     (fold 
635      (lambda (system last-system)
636     
637        
638        (if (not (and last-system
639                      (equal? (paper-system-layout last-system)
640                              (paper-system-layout system))))
641            (set! score-system-list (cons '() score-system-list)))
642        
643        (if (paper-system-layout system)
644            (set-car! score-system-list (cons system (car score-system-list))))
645
646        ;; pass value.
647        system)
648
649      #f 
650      systems)
651
652     (for-each
653      (lambda (system-list)
654        (clip-score-systems
655         (if (> count 0)
656             (format "~a-~a" basename count)
657             basename)
658         system-list))
659
660      score-system-list)))
661
662
663 (define-public (output-preview-framework basename book scopes fields)
664   (let* ((paper (ly:paper-book-paper book))
665          (systems (ly:paper-book-systems book))
666          (scale (ly:output-def-lookup paper 'output-scale))
667          (to-dump-systems '()))
668
669     ;; skip booktitles.
670     (if (and
671          (not (ly:get-option 'include-book-title-preview))
672          (pair? systems)
673          (ly:prob-property (car systems) 'is-book-title #f))
674
675         (set! systems (cdr systems)))
676
677     (for-each
678      (lambda (sys)
679        (if (or
680             (paper-system-title? sys)
681             (not (pair? to-dump-systems))
682             (paper-system-title? (car to-dump-systems)))
683            (set! to-dump-systems (cons sys to-dump-systems))))
684      systems)
685
686     (dump-stencil-as-EPS
687      paper
688      (stack-stencils Y DOWN 0.0
689                      (map paper-system-stencil (reverse to-dump-systems)))
690      (format "~a.preview" basename)
691      #t)
692
693     (postprocess-output book framework-ps-module
694                         (format "~a.preview.eps" basename)
695                         (cons "png" (ly:output-formats)))))
696
697 (if #f
698     (define-public (output-preview-framework basename book scopes fields)
699
700       (let* ((paper (ly:paper-book-paper book))
701              (systems (ly:paper-book-systems book))
702              (scale (ly:output-def-lookup paper 'output-scale))
703              (titles (take-while paper-system-title? systems))
704              (non-title (find (lambda (x)
705                                 (not (paper-system-title? x))) systems))
706              (dump-me
707               (stack-stencils Y DOWN 0.0
708                               (map paper-system-stencil
709                                    (append titles (list non-title))))))
710         (output-scopes scopes fields basename)
711         (dump-stencil-as-EPS paper dump-me
712                              (format "~a.preview" basename)
713                              #t)
714
715         (postprocess-output book framework-ps-module
716                             (format "~a.preview.eps" basename)
717                              (ly:output-formats)))))
718
719 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
720
721 (define-public (convert-to-pdf book name)
722   (let* ((defs (ly:paper-book-paper book))
723          (landscape (ly:output-def-lookup defs 'landscape))
724          (output-scale (ly:output-def-lookup defs 'output-scale))
725          (convert (lambda (x) (* x output-scale (/ (ly:bp 1)))))
726          
727          (paper-width (convert (ly:output-def-lookup defs 'paper-width)))
728          (paper-height (convert (ly:output-def-lookup defs 'paper-height)))
729
730          (w (if landscape paper-height paper-width))
731          (h (if landscape paper-width paper-height))
732          )
733
734     (if (equal? (basename name ".ps") "-")
735         (ly:warning (_ "cannot convert <stdout> to ~S" "PDF"))
736         (postscript->pdf w h name))))
737
738 (define-public (convert-to-png book name)
739   (let* ((defs (ly:paper-book-paper book))
740          (defs-resolution (ly:output-def-lookup defs 'pngresolution))
741          (resolution (if (number? defs-resolution)
742                          defs-resolution
743                          (ly:get-option 'resolution)))
744          (paper-width (ly:output-def-lookup defs 'paper-width))
745          (paper-height (ly:output-def-lookup defs 'paper-height))
746          (output-scale (ly:output-def-lookup defs 'output-scale)))
747
748     (postscript->png resolution
749                      (* paper-width output-scale (/ (ly:bp 1)))
750                      (* paper-height output-scale (/ (ly:bp 1)))
751                      name)))
752
753 (define-public (convert-to-dvi book name)
754   (ly:warning (_ "cannot generate ~S using the postscript back-end") "DVI"))
755
756 (define-public (convert-to-tex book name)
757   (ly:warning (_ "cannot generate ~S using the postscript back-end") "TeX"))
758
759 (define-public (convert-to-ps book name)
760   #t)
761
762 (define-public (output-classic-framework basename book scopes fields)
763
764   (ly:error (_ "\nThe PostScript backend does not support the system-by-system 
765 output. For that, use the EPS backend instead,
766
767   lilypond -dbackend=eps FILE
768
769 If have cut & pasted a lilypond fragment from a webpage, be sure
770 to only remove anything before
771
772   %% ****************************************************************
773   %% Start cut-&-pastable-section
774   %% ****************************************************************
775 ")))