On Wed, Sep 05, 2012 at 01:17:35AM -0700, eluze wrote:
> 
> Frank Steinmetzger wrote
> > 
> > 
> > While the empty staves get removed as expected, using this feature breaks
> > the
> > merge-rests code -- I get two rests above each other.  
> > 
> 
> for me it works - can you provide an example?

OK, finally I found the time to deal with this.  I found out that among the
things that \RemoveEmptyStaffContext changes are the settings that merge rests.

I attached a mini-example to demonstrate.  In my normal setup I have a global
include file which pre-defines some layout stuff.  It has a layout block which,
to enable merging of rests, contains:

\context {
  \Staff
  \override RestCollision #'positioning-done = #merge-rests-on-positioning
  \override MultiMeasureRest #'Y-offset = #merge-multi-measure-rests-on-Y-offset
}

I simulated this in my attached example by having a \layout block at the top
of the file.  The result is that, as soon as I add \RemoveEmptyStaffContext to
the score, the rests are no longer merged.  I need to repeat the code from the
global \layout block in the score's \layout (*below* \RemoveEmptyStaffContext).
-- 
Gruß | Greetings | Qapla'
Please do not share anything from, with or about me with any Facebook service.

They say memory is the second thing to go.  I forgot what the first thing was.
#(define (rest-score r)
  (let ((score 0)
        (yoff (ly:grob-property-data r 'Y-offset))
        (sp (ly:grob-property-data r 'staff-position)))
    (if (number? yoff)
        (set! score (+ score 2))
        (if (eq? yoff 'calculation-in-progress)
            (set! score (- score 3))))
    (and (number? sp)
         (<= 0 2 sp)
         (set! score (+ score 2))
         (set! score (- score (abs (- 1 sp)))))
    score))

#(define (merge-rests-on-positioning grob)
  (let* ((can-merge #f)
         (elts (ly:grob-object grob 'elements))
         (num-elts (and (ly:grob-array? elts)
                        (ly:grob-array-length elts)))
         (two-voice? (= num-elts 2)))
    (if two-voice?
        (let* ((v1-grob (ly:grob-array-ref elts 0))
               (v2-grob (ly:grob-array-ref elts 1))
               (v1-rest (ly:grob-object v1-grob 'rest))
               (v2-rest (ly:grob-object v2-grob 'rest)))
          (and
           (ly:grob? v1-rest)
           (ly:grob? v2-rest)
           (let* ((v1-duration-log (ly:grob-property v1-rest 'duration-log))
                  (v2-duration-log (ly:grob-property v2-rest 'duration-log))
                  (v1-dot (ly:grob-object v1-rest 'dot))
                  (v2-dot (ly:grob-object v2-rest 'dot))
                  (v1-dot-count (and (ly:grob? v1-dot)
                                     (ly:grob-property v1-dot 'dot-count -1)))
                  (v2-dot-count (and (ly:grob? v2-dot)
                                     (ly:grob-property v2-dot 'dot-count -1))))
             (set! can-merge
                   (and
                    (number? v1-duration-log)
                    (number? v2-duration-log)
                    (= v1-duration-log v2-duration-log)
                    (eq? v1-dot-count v2-dot-count)))
             (if can-merge
                 ;; keep the rest that looks best:
                 (let* ((keep-v1? (>= (rest-score v1-rest)
                                      (rest-score v2-rest)))
                        (rest-to-keep (if keep-v1? v1-rest v2-rest))
                        (dot-to-kill (if keep-v1? v2-dot v1-dot)))
                   ;; uncomment if you're curious of which rest was chosen:
                   ;;(ly:grob-set-property! v1-rest 'color green)
                   ;;(ly:grob-set-property! v2-rest 'color blue)
                   (ly:grob-suicide! (if keep-v1? v2-rest v1-rest))
                   (if (ly:grob? dot-to-kill)
                       (ly:grob-suicide! dot-to-kill))
                   (ly:grob-set-property! rest-to-keep 'direction 0)
                   (ly:rest::y-offset-callback rest-to-keep)))))))
    (if can-merge
        #t
        (ly:rest-collision::calc-positioning-done grob))))

#(define merge-multi-measure-rest-on-Y-offset
  ;; Call this to get the 'Y-offset of a MultiMeasureRest.
  ;; It keeps track of other MultiMeasureRests in the same NonMusicalPaperColumn
  ;; and StaffSymbol. If two are found, make transparent one and return 1 for 
Y-offset of
  ;; the other one.
  (let ((table (make-weak-key-hash-table)))
    (lambda (grob)
      (let* ((ssymb (ly:grob-object grob 'staff-symbol))
             (nmcol (ly:grob-parent grob X))
             (ssymb-hash (begin
               (if (not (hash-ref table ssymb))
                   (hash-set! table ssymb (make-hash-table 1)))
               (hash-ref table ssymb)))
             (othergrob (hash-ref ssymb-hash nmcol))
             (measure-count (if (ly:grob? grob) 
                        (ly:grob-property grob 'measure-count)
                        0)))

            (if (ly:grob? othergrob)
              (begin 
                ;; Make merged rest transparent instead of suiciding
                ;; in case it supports text/counter
                    
                (set! (ly:grob-property othergrob 'transparent) #t)
                (hash-remove! ssymb-hash nmcol)
                (if (<= (string->number (cadr (string-split (lilypond-version) 
#\.))) 14)
                    0
                    (if (< 1 measure-count)
                        0
                        1))
                )
              (begin
                ;; Just save this grob and return the default value
                (hash-set! ssymb-hash nmcol grob)
                (ly:staff-symbol-referencer::callback grob)))
                ))))

mergeRestsOn = {
  \override Staff.RestCollision #'positioning-done = #merge-rests-on-positioning
  \override Staff.MultiMeasureRest #'Y-offset = 
#merge-multi-measure-rest-on-Y-offset
}

mergeRestsOff = {
  \revert Staff.RestCollision #'positioning-done
  \revert Staff.MultiMeasureRest #'Y-offset
}

mergeRests = \with {
  \override RestCollision #'positioning-done = #merge-rests-on-positioning
  \override MultiMeasureRest #'Y-offset = #merge-multi-measure-rest-on-Y-offset
}

mmrtr =  \override Voice.MultiMeasureRestNumber #'transparent = ##t
\version "2.14.2"

% Snippet to auto-merge rests
\include "336.ily"

\paper {
        ragged-right = ##t
}

notesone=\relative c'' {
        a4 b r b
        R1
        a1
}

notestwo=\relative c'{
        f4 r r f
        R1
        c1
}

\layout {
        \context {
                \Staff
                \override RestCollision #'positioning-done = 
#merge-rests-on-positioning
                \override MultiMeasureRest #'Y-offset = 
#merge-multi-measure-rest-on-Y-offset
        }
}
\score {
<<
        \new Staff {
                \clef treble
                \time 4/4
                \new Voice = "EmptyFirst" \relative c'' {
                        R1 * 3
                        c1~
                        c1~
                        c1
                }
        }
        \new Staff {
                \clef treble
                \time 4/4
                <<
                        \new Voice = "VoiceOne" {
                                \voiceOne
                                \notesone \break
                                \notesone
                        }
                        \new Voice = "VoiceTwo" {
                                \voiceTwo
                                \notestwo
                                \notestwo
                        }
                >>
        }
>>
        \layout {
                indent = #0
                \context { \RemoveEmptyStaffContext }
                \context {
                        \Score
                        \override VerticalAxisGroup #'remove-first = ##t
                }

                % for rest-merges to work, I need to write the following again
                %\context {
                %       \Staff
                %       \override RestCollision #'positioning-done = 
#merge-rests-on-positioning
                %       \override MultiMeasureRest #'Y-offset = 
#merge-multi-measure-rest-on-Y-offset
                %}
        }
}

Attachment: signature.asc
Description: Digital signature

_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user

Reply via email to