(lambda (elt)
(grob::has-interface elt symbol)))
-(define-public ((outputproperty-compatibility func sym val) grob g-context ao-context)
+(define ((outputproperty-compatibility func sym val) grob g-context ao-context)
(if (func grob)
(set! (ly:grob-property grob sym) val)))
+(export outputproperty-compatibility)
-(define-public ((set-output-property grob-name symbol val) grob grob-c context)
+(define ((set-output-property grob-name symbol val) grob grob-c context)
"Usage example:
@code{\\applyoutput #(set-output-property 'Clef 'extra-offset '(0 . 1))}"
(let ((meta (ly:grob-property grob 'meta)))
(if (equal? (assoc-get 'name meta) grob-name)
(set! (ly:grob-property grob symbol) val))))
+(export set-output-property)
(define-public (skip->rest mus)
(and clef (make-cue-clef-unset))))))
quote-music))
-(define-public ((quote-substitute quote-tab) music)
+(define ((quote-substitute quote-tab) music)
(let* ((quoted-name (ly:music-property music 'quoted-music-name))
(quoted-vector (and (string? quoted-name)
(hash-ref quote-tab quoted-name #f))))
ly:quote-iterator::constructor))
(ly:music-warning music (ly:format (_ "cannot find quoted music: `~S'") quoted-name))))
music))
+(export quote-substitute)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(cons need-restore need-accidental)))
-(define-public ((make-accidental-rule octaveness laziness) context pitch barnum measurepos)
+(define ((make-accidental-rule octaveness laziness) context pitch barnum measurepos)
"Create an accidental rule that makes its decision based on the octave of
the note and a laziness value.
immediately', that is, only look at key signature. @code{#t} is `forever'."
(check-pitch-against-signature context pitch barnum laziness octaveness #f))
+(export make-accidental-rule)
-(define-public ((make-accidental-dodecaphonic-rule octaveness laziness) context pitch barnum measurepos)
+(define ((make-accidental-dodecaphonic-rule octaveness laziness) context pitch barnum measurepos)
"Variation on function make-accidental-rule that creates an dodecaphonic
accidental rule."
(check-pitch-against-signature context pitch barnum laziness octaveness #t))
+(export make-accidental-dodecaphonic-rule)
(define (key-entry-notename entry)
"Return the pitch of an @var{entry} in @code{localAlterations}.
0))
(define-public (find-pitch-entry keysig pitch accept-global accept-local)
- "Return the first entry in @var{keysig} that matches @var{pitch}.
+ "Return the first entry in @var{keysig} that matches @var{pitch}
+by notename and octave. Alteration is not considered.
@var{accept-global} states whether key signature entries should be included.
@var{accept-local} states whether local accidentals should be included.
If no matching entry is found, @var{#f} is returned."
note (just as in the dodecaphonic accidental style) @emph{except} if
the note is immediately preceded by a note with the same pitch. This
is a common accidental style in contemporary notation."
- (let* ((keysig (ly:context-property context 'localKeySignature))
- (entry (find-pitch-entry keysig pitch #t #t)))
+ (let* ((keysig (ly:context-property context 'localAlterations))
+ (entry (find-pitch-entry keysig pitch #f #t)))
(if (not entry)
- (cons #f #t)
- (let* ((entrymp (key-entry-measure-position entry))
- (entrybn (key-entry-bar-number entry)))
- (cons #f
- (not
- (and (equal? entrybn barnum) (equal? entrymp measurepos))))))))
+ (cons #f #t)
+ (let ((entrymp (key-entry-measure-position entry))
+ (entrybn (key-entry-bar-number entry))
+ (entryalt (key-entry-alteration entry))
+ (alt (ly:pitch-alteration pitch)))
+ (cons #t
+ (not (and (equal? entrybn barnum)
+ (or (equal? measurepos entrymp)
+ (ly:moment<? measurepos entrymp))
+ (equal? entryalt alt))))))))
(define-public (teaching-accidental-rule context pitch barnum measurepos)
"An accidental rule that typesets a cautionary accidental if it is
;; repeated notes (in the same voice) don't get an accidental
((equal? style 'dodecaphonic-no-repeat)
(set-accidentals-properties #f
- `(Staff ,(make-accidental-rule 'same-octave 0)
- ,dodecaphonic-no-repeat-rule)
- '()
- context))
+ `(Staff ,dodecaphonic-no-repeat-rule)
+ '()
+ context))
;; Variety of the dodecaphonic style. Each note gets an accidental,
;; except notes that were already handled in the same measure.
((equal? style 'dodecaphonic-first)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; The following is used by the alterBroken function.
-(define-public ((value-for-spanner-piece arg) grob)
+(define ((value-for-spanner-piece arg) grob)
"Associate a piece of broken spanner @var{grob} with an element
of list @var{arg}."
(let* ((orig (ly:grob-original grob))
(if (>= (length siblings) 2)
(helper siblings arg)
(car arg))))
+(export value-for-spanner-piece)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; measure counter
self)
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; The following are used by \magnifyMusic
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; \magnifyMusic and \magnifyStaff
-(define-public (scale-fontSize mag)
- "Used by @code{\\magnifyMusic}. Look up the current fontSize and
-scale it by the magnification factor @var{mag}."
+;; defined as a function instead of a list because the
+;; all-grob-descriptions alist is not available yet
+(define-public (find-all-space-alist-props grob-descriptions)
+ "Used by @code{\\magnifyStaff}. When @var{grob-descriptions} is equal
+to the @code{all-grob-descriptions} alist (defined in
+@file{scm/define-grobs.scm}), this will find all grobs that have an
+initialized value for the @code{space-alist} property, and return them
+as a list in the following format:
+@example
+'((Ambitus space-alist)
+ (BarLine space-alist)
+ ...)
+@end example"
+ (define (has-space-alist? grob-desc)
+ (ly:assoc-get 'space-alist (cdr grob-desc)))
+ (let* ((grob-descriptions-with-space-alist
+ (filter has-space-alist? grob-descriptions))
+ (grob-names-with-space-alist
+ (map car grob-descriptions-with-space-alist)))
+ (map (lambda (grob-name) (list grob-name 'space-alist))
+ grob-names-with-space-alist)))
+
+(define (magnifyStaff-is-set? context mag)
+ (let* ((Staff (ly:context-find context 'Staff))
+ (old-mag (ly:context-property Staff 'magnifyStaffValue)))
+ (not (null? old-mag))))
+
+(define (staff-magnification-is-changing? context mag)
+ (let* ((Staff (ly:context-find context 'Staff))
+ (old-mag (ly:context-property Staff 'magnifyStaffValue 1)))
+ (not (= old-mag mag))))
+
+(define-public (scale-fontSize func-name mag)
+ "Used by @code{\\magnifyMusic} and @code{\\magnifyStaff}. Look up the
+current @code{fontSize} in the appropriate context and scale it by the
+magnification factor @var{mag}. @var{func-name} is either
+@code{'magnifyMusic} or @code{'magnifyStaff}."
(make-apply-context
(lambda (context)
- (let* ((fontSize (ly:context-property context 'fontSize 0))
- (new-fontSize (+ fontSize (magnification->font-size mag))))
- (ly:context-set-property! context 'fontSize new-fontSize)))))
-
-(define-public (revert-fontSize mag)
- "Used by @code{\\magnifyMusic}. Calculate the previous fontSize value
-(before scaling) by factoring out the magnification factor @var{mag}."
+ (if (or (eq? func-name 'magnifyMusic)
+ ;; for \magnifyStaff, only scale the fontSize
+ ;; if staff magnification is changing
+ (staff-magnification-is-changing? context mag))
+ (let* ((where (case func-name
+ ((magnifyMusic) context)
+ ((magnifyStaff) (ly:context-find context 'Staff))))
+ (fontSize (ly:context-property where 'fontSize 0))
+ (new-fontSize (+ fontSize (magnification->font-size mag))))
+ (ly:context-set-property! where 'fontSize new-fontSize))))))
+
+(define-public (revert-fontSize func-name mag)
+ "Used by @code{\\magnifyMusic} and @code{\\magnifyStaff}. Calculate
+the previous @code{fontSize} value (before scaling) by factoring out the
+magnification factor @var{mag} (if @var{func-name} is
+@code{'magnifyMusic}), or by factoring out the context property
+@code{magnifyStaffValue} (if @var{func-name} is @code{'magnifyStaff}).
+Revert the @code{fontSize} in the appropriate context accordingly.
+
+With @code{\\magnifyMusic}, the scaling is reverted after the music
+block it operates on. @code{\\magnifyStaff} does not operate on a music
+block, so the scaling from a previous call (if there is one) is reverted
+before the new scaling takes effect."
(make-apply-context
(lambda (context)
- (let* ((fontSize (ly:context-property context 'fontSize 0))
- (old-fontSize (- fontSize (magnification->font-size mag))))
- (ly:context-set-property! context 'fontSize old-fontSize)))))
-
-(define-public (scale-props props mag allowed-to-shrink?)
- "Used by @code{\\magnifyMusic}. For each prop in @var{props}, find
-the current value of the requested prop, scale it by the magnification
-factor @var{mag}, and do the equivalent of a
-@code{\\temporary@tie{}\\override} with the new value. If
-@code{allowed-to-shrink?} is @code{#f}, don't let the new value be less
-than the current value. Props are formatted like:
-
+ (if (or (eq? func-name 'magnifyMusic)
+ ;; for \magnifyStaff...
+ (and
+ ;; don't revert the user's fontSize choice
+ ;; the first time \magnifyStaff is called
+ (magnifyStaff-is-set? context mag)
+ ;; only revert the previous fontSize
+ ;; if staff magnification is changing
+ (staff-magnification-is-changing? context mag)))
+ (let* ((where
+ (case func-name
+ ((magnifyMusic) context)
+ ((magnifyStaff) (ly:context-find context 'Staff))))
+ (old-mag
+ (case func-name
+ ((magnifyMusic) mag)
+ ((magnifyStaff)
+ (ly:context-property where 'magnifyStaffValue 1))))
+ (fontSize (ly:context-property where 'fontSize 0))
+ (old-fontSize (- fontSize (magnification->font-size old-mag))))
+ (ly:context-set-property! where 'fontSize old-fontSize))))))
+
+(define-public (scale-props func-name mag allowed-to-shrink? props)
+ "Used by @code{\\magnifyMusic} and @code{\\magnifyStaff}. For each
+prop in @var{props}, find the current value of the requested prop, scale
+it by the magnification factor @var{mag}, and do the equivalent of a
+@code{\\temporary@tie{}\\override} with the new value in the appropriate
+context. If @var{allowed-to-shrink?} is @code{#f}, don't let the new
+value be less than the current value. @var{func-name} is either
+@code{'magnifyMusic} or @code{'magnifyStaff}. The @var{props} list is
+formatted like:
@example
-Slur.height-limit
-Slur.details.region-size
+'((Stem thickness)
+ (Slur line-thickness)
+ ...)
@end example"
(make-apply-context
(lambda (context)
- (define (scale-prop grob.prop)
- (let* ((grob-prop-list (map string->symbol
- (string-split
- (symbol->string grob.prop) #\.)))
- (prop-is-alist? (eq? 3 (length grob-prop-list)))
- (grob (car grob-prop-list))
+ (define (scale-prop grob-prop-list)
+ (let* ((grob (car grob-prop-list))
(prop (cadr grob-prop-list))
(where (if (eq? grob 'SpacingSpanner)
(ly:context-find context 'Score)
- context))
+ (case func-name
+ ((magnifyMusic) context)
+ ((magnifyStaff) (ly:context-find context 'Staff)))))
(grob-def (ly:context-grob-definition where grob)))
- (if prop-is-alist?
- (let* ((subprop (caddr grob-prop-list))
- (old-alist (ly:assoc-get prop grob-def))
- (val (ly:assoc-get subprop old-alist 1))
- (round-if-needed
- (lambda (x)
- ;; these props require exact integers
- (if (or (eq? subprop 'multi-tie-region-size)
- (eq? subprop 'single-tie-region-size))
- (inexact->exact (round x))
- x)))
- (new-val (if allowed-to-shrink?
- (round-if-needed (* val mag))
- (round-if-needed (* val (max 1 mag)))))
- (new-alist (cons (cons subprop new-val) old-alist)))
+ (if (eq? prop 'space-alist)
+ (let* ((space-alist (ly:assoc-get prop grob-def))
+ (scale-spacing-tuple (lambda (x)
+ (cons (car x)
+ (cons (cadr x)
+ (* mag (cddr x))))))
+ (scaled-tuples (map scale-spacing-tuple space-alist))
+ (new-alist (append scaled-tuples space-alist)))
(ly:context-pushpop-property where grob prop new-alist))
(let* ((val (ly:assoc-get prop grob-def 1))
(proc (lambda (x)
(proc (cdr val)))
(proc val))))
(ly:context-pushpop-property where grob prop new-val)))))
- (for-each scale-prop props))))
-
+ (if (or (eq? func-name 'magnifyMusic)
+ ;; for \magnifyStaff, only scale the properties
+ ;; if staff magnification is changing
+ (staff-magnification-is-changing? context mag))
+ (for-each scale-prop props)))))
+
+(define-public (revert-props func-name mag props)
+ "Used by @code{\\magnifyMusic} and @code{\\magnifyStaff}. Revert each
+prop in @var{props} in the appropriate context. @var{func-name} is
+either @code{'magnifyMusic} or @code{'magnifyStaff}. The @var{props}
+list is formatted like:
+@example
+'((Stem thickness)
+ (Slur line-thickness)
+ ...)
+@end example"
+ (make-apply-context
+ (lambda (context)
+ (define (revert-prop grob-prop-list)
+ (let* ((grob (car grob-prop-list))
+ (prop (cadr grob-prop-list))
+ (where (if (eq? grob 'SpacingSpanner)
+ (ly:context-find context 'Score)
+ (case func-name
+ ((magnifyMusic) context)
+ ((magnifyStaff) (ly:context-find context 'Staff))))))
+ (ly:context-pushpop-property where grob prop)))
+ (if (or (eq? func-name 'magnifyMusic)
+ ;; for \magnifyStaff...
+ (and
+ ;; don't revert the user's property overrides
+ ;; the first time \magnifyStaff is called
+ (magnifyStaff-is-set? context mag)
+ ;; revert the overrides from the previous \magnifyStaff,
+ ;; but only if staff magnification is changing
+ (staff-magnification-is-changing? context mag)))
+ (for-each revert-prop props)))))
+
+;; \magnifyMusic only
(define-public (scale-beam-thickness mag)
"Used by @code{\\magnifyMusic}. Scaling @code{Beam.beam-thickness}
-exactly to the @var{mag} value won't work. This uses two reference
+exactly to the @var{mag} value will not work. This uses two reference
values for @code{beam-thickness} to determine an acceptable value when
scaling, then does the equivalent of a
@code{\\temporary@tie{}\\override} with the new value."
(scaled-default (+ 119/925 (* mag 13/37)))
(new-val (* scaled-default ratio-to-default)))
(ly:context-pushpop-property context 'Beam 'beam-thickness new-val)))))
-
-(define-public (revert-props props)
- "Used by @code{\\magnifyMusic}. Revert each prop in @var{props}.
-Props are formatted like:
-
-@example
-Slur.height-limit
-Slur.details.region-size
-@end example
-
-Nested properties are reverted by reverting the parent property only.
-For example, @code{Slur.details.region-size} gets reverted like this:
-
-@example
-\revert Slur.details
-@end example
-
-This is safe as long as the number of reverts matches the number of
-overrides. Any user overrides within a @code{\\magnifyMusic} block
-should be reverted before closing the block."
- (make-apply-context
- (lambda (context)
- (define (revert-prop grob.prop)
- (let* ((grob-prop-list (map string->symbol
- (string-split
- (symbol->string grob.prop) #\.)))
- (grob (car grob-prop-list))
- (prop (cadr grob-prop-list))
- (where (if (eq? grob 'SpacingSpanner)
- (ly:context-find context 'Score)
- context)))
- (ly:context-pushpop-property where grob prop)))
- (for-each revert-prop props))))