From 0b972615532ee9d62d0e2c7ebe94fc50f980f389 Mon Sep 17 00:00:00 2001 From: "zuk (Jakob Krueger)" Date: Thu, 23 Oct 2025 23:31:28 +0200 Subject: [PATCH] Fix black rests in secondVoiceStyle --- private_includes/base/all.ily | 1 + .../base/basic_format_and_style_settings.ily | 6 +- .../base/merge_rests_engraver_override.ily | 86 +++++++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 private_includes/base/merge_rests_engraver_override.ily diff --git a/private_includes/base/all.ily b/private_includes/base/all.ily index 3376e3a..0b74ffc 100644 --- a/private_includes/base/all.ily +++ b/private_includes/base/all.ily @@ -24,6 +24,7 @@ #(define AUTHOR_DATA (if (defined? 'AUTHOR_DATA) AUTHOR_DATA (parse-yml-file "../../lilypond-song-includes/data/authors.yml"))) #(define SONG_DATA (if (defined? 'SONG_DATA) SONG_DATA (parse-yml-file "../../lilypond-song-includes/data/songs.yml"))) +\include "merge_rests_engraver_override.ily" \include "basic_format_and_style_settings.ily" \include "eps_file_from_song_dir.ily" \include "title_with_category_images.ily" diff --git a/private_includes/base/basic_format_and_style_settings.ily b/private_includes/base/basic_format_and_style_settings.ily index 2c4b2d9..49b44c4 100644 --- a/private_includes/base/basic_format_and_style_settings.ily +++ b/private_includes/base/basic_format_and_style_settings.ily @@ -44,7 +44,7 @@ generalLayout = \layout { \context { \Staff \accidentalStyle modern-voice-cautionary - \consists Merge_rests_engraver + \consists \Better_Merge_rests_engraver } \context { \Score @@ -67,6 +67,7 @@ generalLayout = \layout { % ich will lines breaken wie ich will! \remove "Forbid_line_break_engraver" \override NoteHead.layer = 2 + \override Rest.layer = 2 \override Dots.layer = 2 \override Stem.layer = 2 \override Flag.layer = 2 @@ -83,12 +84,14 @@ textp = \lyricmode { \markup { \raise #1 \musicglyph #"rests.3" } } % zweite Stimme alles grau secondVoiceStyle = { \override NoteHead.color = #grey + \override Rest.color = #grey \override Dots.color = #grey \override Stem.color = #grey \override Flag.color = #grey \override Beam.color = #grey \override Accidental.color = #grey \override NoteHead.layer = 1 + \override Rest.layer = 1 \override Dots.layer = 1 \override Stem.layer = 1 \override Flag.layer = 1 @@ -98,6 +101,7 @@ secondVoiceStyle = { firstVoiceStyle = { \override NoteHead.color = #black + \override Rest.color = #black \override Dots.color = #black \override Stem.color = #black \override Flag.color = #black diff --git a/private_includes/base/merge_rests_engraver_override.ily b/private_includes/base/merge_rests_engraver_override.ily new file mode 100644 index 0000000..6a2be85 --- /dev/null +++ b/private_includes/base/merge_rests_engraver_override.ily @@ -0,0 +1,86 @@ +Better_Merge_rests_engraver = +#(lambda (context) + (define (has-one-or-less? lst) (or (null? lst) (null? (cdr lst)))) + (define (has-at-least-two? 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)))) + (define (measure-count-eqv? a b) + (eqv? + (ly:grob-property a 'measure-count) + (ly:grob-property b 'measure-count))) + + (define (rests-all-unpitched? rests) + "Returns true when all rests do not override the staff-position grob + property. When a rest has a position set we do not want to merge rests at + that position." + (every (lambda (rest) (null? (ly:grob-property rest 'staff-position))) rests)) + + (define (less-by-layer a b) + (< + (ly:grob-property b 'layer) + (ly:grob-property a 'layer))) + + (define (merge-mmrests mmrests) + "Move all multimeasure rests to the single voice location." + (if (all-equal? mmrests measure-count-eqv?) + (begin + (for-each + (lambda (rest) (ly:grob-set-property! rest 'direction CENTER)) + mmrests) + (for-each + (lambda (rest) (ly:grob-set-property! rest 'transparent #t)) + (cdr (sort mmrests less-by-layer)))))) + + (define (merge-rests rests) + (for-each + (lambda (rest) (ly:grob-set-property! rest 'staff-position 0)) + rests) + (for-each + (lambda (rest) (ly:grob-set-property! rest 'transparent #t)) + (cdr (sort rests less-by-layer)))) + + (let ((mmrests '()) + (rests '()) + (dots '())) + (make-engraver + ((start-translation-timestep translator) + (set! rests '()) + (set! mmrests '()) + (set! dots '())) + (acknowledgers + ((dot-column-interface engraver grob source-engraver) + (if (not (ly:context-property context 'suspendRestMerging #f)) + (set! + dots + (append (ly:grob-array->list (ly:grob-object grob 'dots)) + dots)))) + ((rest-interface engraver grob source-engraver) + (cond + ((ly:context-property context 'suspendRestMerging #f) + #f) + ((grob::has-interface grob 'multi-measure-rest-interface) + (set! mmrests (cons grob mmrests))) + (else + (set! rests (cons grob rests)))))) + ((stop-translation-timestep translator) + (let (;; get a list of the rests 'duration-lengths, 'duration-log does + ;; not take dots into account + (durs + (map + (lambda (g) + (ly:duration->moment + (ly:prob-property + (ly:grob-property g 'cause) + 'duration))) + rests))) + (if (and + (has-at-least-two? rests) + (all-equal? durs equal?) + (rests-all-unpitched? rests)) + (begin + (merge-rests rests) + ;; ly:grob-suicide! works nicely for dots, as opposed to rests. + (if (pair? dots) (for-each ly:grob-suicide! (cdr dots))))) + (if (has-at-least-two? mmrests) + (merge-mmrests mmrests))))))) \ No newline at end of file