Thomas Morley wrote:
> 
> Anyway, if you want to have the dots for rests affected as well, you
> need to adress them through the Rest:
> 
> \version "2.19.25"
> 
> omit-rest-and-dots =
> \override Rest.after-line-breaking =
>   #(lambda (grob)
>     (ly:grob-set-property! grob 'stencil #f)
>     (if (not (null? (ly:grob-object grob 'dot)))
>         (ly:grob-set-property! (ly:grob-object grob 'dot) 'stencil #f)))
> 
> centerRests = {
>   \override Rest.staff-position = #0
> }
> 
> \new Staff <<
>   \new Voice
>   \relative c'' {
>     \voiceOne
>     \omit-rest-and-dots
>     r4  c  r  d | r2. e4
>     d2. e4
>   }
>   \new Voice
>   \relative c'' {
>     \voiceTwo
>     \centerRests
>     r4 a8 a8 r4 b8 b8 | r2. c4
>     c2. a4
>   }
>

Great, that is just the information I was missing in order to fix
Jay's Scheme code. Attached is an updated version of

https://github.com/openlilylib/openlilylib/blob/master/editorial-tools/merge-rests-engraver/definition.ily

that now works correctly for dotted rests (as well as double-dotted
rests, full-measure rests, and so on). I am attaching the full file,
as well as a patch.

I factored the actual rest-merging code into a separate Scheme
function that is shared by both merge-rests-engraver and
merge-mmrests-engraver -- this is probably technically unnecessary
because multi-measure rests are not usually dotted. Still I think it
is better to engrave just one glyph for the merged rests, rather than
a bunch of identical glyphs at the same coordinate. Also, having it as
a separate function is easier to comprehend than deeply-nested Scheme.

Here's an example showing it all in action:

%----------------------------------------
\version "2.19.25"

\include "definition.ily"

\layout {
  \context { \Staff \consists #merge-rests-engraver }
  \context { \Staff \consists #merge-mmrests-engraver }
}

\new Staff <<
  \new Voice {
    \relative c'' {
      \voiceOne
      | r  c  r  d
      | r2. r4
      | r2.. e8
      | r2... e16
      | d2. e4
      | R1
      | c4 c c c
      | R1
    }
  }
  \new Voice {
    \relative c'' {
      \voiceTwo
      | r4 a8 a8 r4 b8 b8
      | r2. c4
      | r2.. c8
      | r2... c16
      | c2. a4
      | R1*3
    }
  }
>>
%----------------------------------------

See rests5.pdf for the output.

If you all agree that this patch works correctly, hopefully someone
with commit privileges can merge it into git?

Thanks, -- Peter
--- definition.ily-orig 2015-08-23 16:16:13.428995010 -0300
+++ definition.ily      2015-08-23 16:13:43.995254184 -0300
@@ -18,6 +18,17 @@
    (or (has-one-or-less lst)
        (and (pred (car lst) (cadr lst)) (all-equal (cdr lst) pred))))
 
+% merge a list of rests, by moving the first one to the specified
+% offset, and disabling all the other ones including any associated dots.
+#(define (merge-to-offset rests offset)
+   (ly:grob-set-property! (car rests) 'Y-offset offset)
+   (for-each
+    (lambda (rest)
+      (ly:grob-set-property! rest 'stencil #f)
+      (if (not (null? (ly:grob-object rest 'dot)))
+         (ly:grob-set-property! (ly:grob-object rest 'dot) 'stencil #f)))
+    (cdr rests)))
+
 #(define merge-rests-engraver
    (lambda (context)
      (let ((rest-same-length
@@ -30,10 +41,7 @@
          (stop-translation-timestep . ,(lambda (trans)
                                          (if (and (has-at-least-two
                                                    rests) (all-equal rests 
rest-same-length))
-                                             (for-each
-                                              (lambda (rest)
-                                                (ly:grob-set-property! rest 
'Y-offset 0))
-                                              rests))))
+                                             (merge-to-offset rests 0))))
          (acknowledgers
           (rest-interface . ,(lambda (engraver grob source-engraver)
                                (if (eq? 'Rest (assoc-ref
@@ -51,10 +59,7 @@
                (if (all-equal rests mmrest-same-length)
                    (let ((offset (if (eq? (ly:grob-property (car rests)
                                             'measure-count) 1) 1 0)))
-                     (for-each
-                      (lambda (rest) (ly:grob-set-property! rest
-                                       'Y-offset offset))
-                      rests)))))
+                     (merge-to-offset rests offset)))))
             (curr-rests '())
             (rests '()))
        `((start-translation-timestep . ,(lambda (trans)

Attachment: rests5.pdf
Description: PDF document, version 1.4

\version "2.18.0"

\header {
  snippet-title = "merge-rests-engraver"
  snippet-author = "Jay Anderson"
  snippet-source =
    "http://www.mail-archive.com/lilypond-user%40gnu.org/msg69608.html";
  snippet-description = \markup {
    Merge rests of equal duration in different voice
  }
  tags = "merge, rest, rests, voice, voices"
  status = "ready"
}

#(define has-one-or-less (lambda (lst) (or (null? lst) (null? (cdr lst)))))
#(define has-at-least-two (lambda (lst) (not (has-one-or-less lst))))
#(define (all-equal lst pred)
   (or (has-one-or-less lst)
       (and (pred (car lst) (cadr lst)) (all-equal (cdr lst) pred))))

% merge a list of rests, by moving the first one to the specified
% offset, and disabling all the other ones including any associated dots.
#(define (merge-to-offset rests offset)
   (ly:grob-set-property! (car rests) 'Y-offset offset)
   (for-each
    (lambda (rest)
      (ly:grob-set-property! rest 'stencil #f)
      (if (not (null? (ly:grob-object rest 'dot)))
          (ly:grob-set-property! (ly:grob-object rest 'dot) 'stencil #f)))
    (cdr rests)))

#(define merge-rests-engraver
   (lambda (context)
     (let ((rest-same-length
            (lambda (rest-a rest-b)
              (eq? (ly:grob-property rest-a 'duration-log)
                   (ly:grob-property rest-b 'duration-log))))
           (rests '()))
       `((start-translation-timestep . ,(lambda (trans)
                                          (set! rests '())))
         (stop-translation-timestep . ,(lambda (trans)
                                         (if (and (has-at-least-two
                                                   rests) (all-equal rests 
rest-same-length))
                                             (merge-to-offset rests 0))))
         (acknowledgers
          (rest-interface . ,(lambda (engraver grob source-engraver)
                               (if (eq? 'Rest (assoc-ref
                                               (ly:grob-property grob 'meta) 
'name))
                                   (set! rests (cons grob rests))))))))))

#(define merge-mmrests-engraver
   (lambda (context)
     (let* ((mmrest-same-length
             (lambda (rest-a rest-b)
               (eq? (ly:grob-property rest-a 'measure-count)
                    (ly:grob-property rest-b 'measure-count))))
            (merge-mmrests
             (lambda (rests)
               (if (all-equal rests mmrest-same-length)
                   (let ((offset (if (eq? (ly:grob-property (car rests)
                                            'measure-count) 1) 1 0)))
                     (merge-to-offset rests offset)))))
            (curr-rests '())
            (rests '()))
       `((start-translation-timestep . ,(lambda (trans)
                                          (set! curr-rests '())))
         (stop-translation-timestep . ,(lambda (trans)
                                         (if (has-at-least-two curr-rests)
                                             (set! rests (cons curr-rests 
rests)))))
         (finalize . ,(lambda (translator)
                        (for-each merge-mmrests rests)))
         (acknowledgers
          (rest-interface . ,(lambda (engraver grob source-engraver)
                               (if (eq? 'MultiMeasureRest (assoc-ref
                                                           (ly:grob-property 
grob 'meta) 'name))
                                   (set! curr-rests (cons grob 
curr-rests))))))))))
_______________________________________________
lilypond-user mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/lilypond-user

Reply via email to