-;;
-;; paper-system.scm -- implement paper-system objects.
-;;
-;; source file of the GNU LilyPond music typesetter
-;;
-;; (c) 2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
-;;
+;;;; This file is part of LilyPond, the GNU music typesetter.
+;;;;
+;;;; Copyright (C) 2006--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
+;;;;
+;;;; LilyPond is free software: you can redistribute it and/or modify
+;;;; it under the terms of the GNU General Public License as published by
+;;;; the Free Software Foundation, either version 3 of the License, or
+;;;; (at your option) any later version.
+;;;;
+;;;; LilyPond is distributed in the hope that it will be useful,
+;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;;; GNU General Public License for more details.
+;;;;
+;;;; You should have received a copy of the GNU General Public License
+;;;; along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
(define-module (scm paper-system))
-(use-modules (lily))
+(use-modules (lily)
+ (srfi srfi-1)
+ (ice-9 optargs))
(define-public (paper-system-title? system)
(equal? #t (ly:prob-property system 'is-title)
- ))
+ ))
+
+(define (system-stencil system-grob main-stencil)
+ (let* ((padding (ly:grob-property system-grob 'in-note-padding #f))
+ (in-notes (if padding (ly:grob-property system-grob 'in-note-stencil) empty-stencil))
+ (in-notes (if in-notes in-notes empty-stencil))
+ (direction (if padding (ly:grob-property system-grob 'in-note-direction) UP)))
+ (if padding
+ (ly:stencil-combine-at-edge main-stencil Y direction in-notes padding)
+ main-stencil)))
(define-public (paper-system-stencil system)
- (ly:prob-property system 'stencil))
+ (let ((main-stencil (ly:prob-property system 'stencil))
+ (system-grob (ly:prob-property system 'system-grob)))
+ (if (ly:grob? system-grob)
+ (system-stencil system-grob main-stencil)
+ main-stencil)))
+
+(define-public (paper-system-layout system)
+ (let*
+ ((g (paper-system-system-grob system)))
+
+ (if (ly:grob? g)
+ (ly:grob-layout g)
+ #f)))
+
+(define-public (paper-system-system-grob paper-system)
+ (ly:prob-property paper-system 'system-grob))
(define-public (paper-system-extent system axis)
(ly:stencil-extent (paper-system-stencil system) axis))
(define-public (paper-system-staff-extents ps)
- (ly:prob-property ps 'refpoint-Y-extent '(0 . 0)))
+ (ly:prob-property ps 'staff-refpoint-extent '(0 . 0)))
(define-public (paper-system-annotate-last system layout)
(let*
(y-extent (paper-system-extent system Y))
(x-extent (paper-system-extent system X))
(stencil (ly:prob-property system 'stencil))
-
+
(arrow (if (number? bottomspace)
- (annotate-y-interval layout
- "bottom-space"
- (cons (- (car y-extent) bottomspace)
- (car y-extent))
- #t)
- #f)))
-
+ (annotate-y-interval layout
+ "bottom-space"
+ (cons (- (car y-extent) bottomspace)
+ (car y-extent))
+ #t)
+ #f)))
+
(if arrow
- (set! stencil
- (ly:stencil-add stencil arrow)))
+ (set! stencil
+ (ly:stencil-add stencil arrow)))
(set! (ly:prob-property system 'stencil)
- stencil)
- ))
-
-(define-public (paper-system-annotate system layout)
+ stencil)
+ ))
+
+
+;; Y-ext and next-Y-ext are either skyline-pairs or extents
+(define*-public (annotate-padding system-Y system-X Y-ext X-ext
+ next-system-Y next-system-X next-Y-ext next-X-ext
+ layout horizon-padding padding #:key (base-color blue))
+ (let* ((eps 0.001)
+ (skyline (and (ly:skyline-pair? Y-ext)
+ (ly:skyline-pair::skyline Y-ext DOWN)))
+ (next-skyline (and (ly:skyline-pair? next-Y-ext)
+ (ly:skyline-pair::skyline next-Y-ext UP)))
+ (annotation-X (cond
+ ((and skyline next-skyline)
+ (-
+ (ly:skyline::get-touching-point skyline next-skyline horizon-padding)
+ horizon-padding))
+ (skyline
+ (ly:skyline::get-max-height-position skyline))
+ (next-skyline
+ (ly:skyline::get-max-height-position next-skyline))
+ (else
+ (max (cdr X-ext)
+ (cdr next-X-ext)))))
+ (annotation-Y (if skyline
+ (ly:skyline::get-height skyline annotation-X)
+ (car Y-ext)))
+ (next-annotation-Y (if next-skyline
+ (- (+ (ly:skyline::get-height next-skyline
+ (- (+ annotation-X system-X)
+ next-system-X))
+ next-system-Y)
+ system-Y)
+ (cdr next-Y-ext)))
+ (padding-blocks (>= next-annotation-Y (- annotation-Y padding eps)))
+ (contrast-color (append (cdr base-color) (list (car base-color))))
+ (color (if padding-blocks contrast-color base-color))
+ (annotation (ly:stencil-translate-axis
+ (annotate-y-interval
+ layout
+ "padding"
+ `(,(- annotation-Y padding). ,annotation-Y)
+ #t
+ #:color color)
+ annotation-X X)))
+ (if (> padding 0.0)
+ annotation
+ empty-stencil)))
+
+
+(define-public (paper-system-annotate system next-system layout)
"Add arrows and texts to indicate which lengths are set."
- (let*
- ((annotations (ly:make-stencil '() (cons 0 2) (cons 0 0)))
- (append-stencil
- (lambda (a b)
- (ly:stencil-combine-at-edge a X RIGHT b 0.5 0)))
-
- (annotate-property
- (lambda (name extent is-length?)
- (set! annotations
- (append-stencil annotations
- (annotate-y-interval layout
- name extent is-length?)))))
-
- (bbox-extent (paper-system-extent system Y))
- (refp-extent (ly:prob-property system 'refpoint-Y-extent))
- (next-space (ly:prob-property system 'next-space
- (ly:output-def-lookup layout 'betweensystemspace)
- ))
- (next-padding (ly:prob-property system 'next-padding
- (ly:output-def-lookup layout 'betweensystempadding)
- ))
-
- )
-
- (if (number-pair? bbox-extent)
- (begin
- (annotate-property "Y-extent"
- bbox-extent #f)
- (annotate-property "next-padding"
- (interval-translate (cons (- next-padding) 0) (car bbox-extent))
- #t)))
-
- ;; titles don't have a refpoint-Y-extent.
- (if (number-pair? refp-extent)
- (begin
- (annotate-property "refpoint-Y-extent"
- refp-extent #f)
-
- (annotate-property "next-space"
- (interval-translate (cons (- next-space) 0) (car refp-extent))
- #t)))
-
-
- (set! (ly:prob-property system 'stencil)
- (ly:stencil-add
- (ly:prob-property system 'stencil)
- (ly:make-stencil
- (ly:stencil-expr annotations)
- (ly:stencil-extent empty-stencil X)
- (ly:stencil-extent empty-stencil Y)
- )))
-
- ))
+ (let* ((grob (ly:prob-property system 'system-grob))
+ (paper-height (ly:output-def-lookup layout 'paper-height))
+ (bottom-margin (ly:output-def-lookup layout 'bottom-margin))
+ (top-margin (ly:output-def-lookup layout 'top-margin))
+ (spaceable-staves (if (ly:grob? grob) (ly:system::get-spaceable-staves grob) '()))
+ (all-staves (if (ly:grob? grob) (ly:system::get-staves grob) '()))
+ (spaceable-staff-annotate
+ (lambda (before-staff after-staff)
+ (let ((before-Y (ly:grob-relative-coordinate before-staff grob Y))
+ (after-Y (ly:grob-relative-coordinate after-staff grob Y)))
+ (annotate-spacing-spec
+ layout
+ ;; FIXME: Improve `ly:get-spacing-spec' to return the
+ ;; name of the used `XXX-XXX-spacing' property, if
+ ;; possible. Right now we have to use the empty
+ ;; string.
+ ""
+ (ly:get-spacing-spec before-staff after-staff)
+ before-Y
+ after-Y))))
+
+ (staff-padding-annotate
+ (lambda (before-staff after-staff)
+ (let ((before-Y (ly:grob-relative-coordinate before-staff grob Y))
+ (before-X (ly:grob-relative-coordinate before-staff grob X))
+ (before-X-ext (ly:grob-extent before-staff before-staff X))
+ (after-Y (ly:grob-relative-coordinate after-staff grob Y))
+ (after-X (ly:grob-relative-coordinate after-staff grob X))
+ (after-X-ext (ly:grob-extent after-staff after-staff X))
+ (skylines (ly:grob-property before-staff 'vertical-skylines))
+ (after-skylines (ly:grob-property after-staff 'vertical-skylines))
+ (padding (assoc-get 'padding
+ (ly:get-spacing-spec before-staff after-staff)
+ 0.0))
+ (horizon-padding (ly:grob-property before-staff
+ 'skyline-horizontal-padding
+ 0.0)))
+ (ly:stencil-translate
+ (annotate-padding
+ before-Y before-X skylines before-X-ext
+ after-Y after-X after-skylines after-X-ext
+ layout horizon-padding padding)
+ (cons before-X before-Y)))))
+
+ (staff-annotations (if (< 1 (length spaceable-staves))
+ (map spaceable-staff-annotate
+ (drop-right spaceable-staves 1)
+ (drop spaceable-staves 1))
+ '()))
+ (staff-padding-annotations (if (< 1 (length all-staves))
+ (map staff-padding-annotate
+ (drop-right all-staves 1)
+ (drop all-staves 1))
+ '()))
+ (estimate-extent (if (ly:grob? grob)
+ (annotate-y-interval layout
+ "extent-estimate"
+ (ly:grob-property grob 'pure-Y-extent)
+ #f)
+ #f))
+
+ (spacing-spec-sym (cond ((and next-system
+ (paper-system-title? system)
+ (paper-system-title? next-system))
+ 'markup-markup-spacing)
+ ((paper-system-title? system)
+ 'markup-system-spacing)
+ ((and next-system
+ (paper-system-title? next-system))
+ 'score-markup-spacing)
+ ((not next-system)
+ 'last-bottom-spacing)
+ ((ly:prob-property system 'last-in-score #f)
+ 'score-system-spacing)
+ (else
+ 'system-system-spacing)))
+ (spacing-spec (ly:output-def-lookup layout spacing-spec-sym))
+ (last-staff-Y (car (paper-system-staff-extents system)))
+ (system-Y (ly:prob-property system 'Y-offset 0.0))
+ (system-X (ly:prob-property system 'X-offset 0.0))
+ (next-system-Y (and next-system
+ (ly:prob-property next-system 'Y-offset 0.0)))
+ (next-system-X (and next-system
+ (ly:prob-property next-system 'X-offset 0.0)))
+ (first-staff-next-system-Y (if next-system
+ (- (+ (cdr (paper-system-staff-extents next-system))
+ system-Y)
+ next-system-Y)
+ (+ system-Y top-margin bottom-margin (- paper-height))))
+
+ (skyline (or
+ (ly:prob-property system 'vertical-skylines #f)
+ (paper-system-extent system Y)))
+ (next-skyline (and next-system
+ (or
+ (ly:prob-property next-system 'vertical-skylines #f)
+ (paper-system-extent next-system Y))))
+ (horizon-padding (and
+ (ly:grob? grob)
+ (ly:grob-property grob 'skyline-horizontal-padding 0)))
+ (padding-annotation (if (skyline-pair-and-non-empty? next-system)
+ (annotate-padding
+ (- system-Y) system-X skyline (paper-system-extent system X)
+ (- next-system-Y) next-system-X next-skyline (paper-system-extent next-system X)
+ layout
+ horizon-padding
+ (assoc-get 'padding spacing-spec 0.0)
+ #:base-color blue)
+ empty-stencil))
+
+ (system-annotation (annotate-spacing-spec
+ layout
+ (symbol->string spacing-spec-sym)
+ spacing-spec
+ last-staff-Y
+ first-staff-next-system-Y))
+ (annotations (ly:stencil-add
+ padding-annotation
+ (stack-stencils Y DOWN 0.0 staff-padding-annotations)
+ (stack-stencils Y DOWN 0.0 (append staff-annotations (list system-annotation))))))
+
+ (if estimate-extent
+ (set! annotations
+ (stack-stencils X RIGHT 5.5
+ (list annotations
+ estimate-extent))))
+
+ (if (not (null? annotations))
+ (set! (ly:prob-property system 'stencil)
+ (ly:stencil-add
+ (ly:prob-property system 'stencil)
+ (ly:make-stencil
+ (ly:stencil-expr annotations)
+ (ly:stencil-extent empty-stencil X)
+ (ly:stencil-extent empty-stencil Y)))))
+ (ly:prob-property system 'stencil)))