]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 1471: Invalidate alterations upon key change rather than forgetting them.
authorDavid Kastrup <dak@gnu.org>
Mon, 4 Apr 2011 13:33:24 +0000 (15:33 +0200)
committerDavid Kastrup <dak@gnu.org>
Thu, 7 Apr 2011 19:04:02 +0000 (21:04 +0200)
lily/clef-engraver.cc
scm/music-functions.scm

index 5551cbc07c6eac64e15f22f47f7060aa96dced9e..5ddfea627e0869149ecc4e1c7d65522d437e1a2f 100644 (file)
@@ -138,6 +138,15 @@ Clef_engraver::process_music ()
   inspect_clef_properties ();
 }
 
+static void apply_on_children (Context *context, SCM fun)
+{
+  scm_call_1(fun, context->self_scm());
+  for (SCM s = context->children_contexts ();
+       scm_is_pair(s); s = scm_cdr (s))
+    apply_on_children(unsmob_context (scm_car(s)), fun);
+}
+  
+
 void
 Clef_engraver::inspect_clef_properties ()
 {
@@ -152,9 +161,8 @@ Clef_engraver::inspect_clef_properties ()
       || scm_equal_p (octavation, prev_octavation_) == SCM_BOOL_F
       || to_boolean (force_clef))
     {
-      set_context_property_on_children (context (),
-                                       ly_symbol2scm ("localKeySignature"),
-                                       get_property ("keySignature"));
+      apply_on_children(context (),
+                       ly_lily_module_constant ("invalidate-alterations"));
       
       set_glyph ();
       if (prev_cpos_ != SCM_BOOL_F || to_boolean (get_property ("firstClef")))
index ed96cfd8d21dcda0cf61430c1596ad2422b72b6b..31b0e58c22ad04f58554388fef2c6ff391206a33 100644 (file)
@@ -1009,12 +1009,18 @@ then revert skipTypesetting."
       #t
       (<= bar-number (+ (cadr alteration-def) laziness))))
 
-(define (is-tied? alteration-def)
-  (let* ((def (if (pair? alteration-def)
-                (car alteration-def)
-                alteration-def)))
+(define (accidental-voided? alteration-def)
+  "Checks an alteration entry for being voided.
+
+Non-key alterations are voided when tying into the next bar or when
+there is a clef change, since neither repetition nor cancellation can
+be omitted when the same note occurs again.
 
-    (if (equal? def 'tied) #t #f)))
+Returns @code{#f} or the reason for the voiding, a symbol."
+  (let* ((def (if (pair? alteration-def)
+                 (car alteration-def)
+                 alteration-def)))
+    (and (symbol? def) def)))
 
 (define (extract-alteration alteration-def)
   (cond ((number? alteration-def)
@@ -1083,7 +1089,7 @@ specifies whether accidentals should be canceled in different octaves."
      ((not (equal? from-key-sig #f))
       (set! previous-alteration from-key-sig)))
 
-    (if (is-tied? previous-alteration)
+    (if (accidental-voided? previous-alteration)
        (set! need-accidental #t)
 
        (let* ((prev-alt (extract-alteration previous-alteration))
@@ -1141,10 +1147,14 @@ immediately', that is, only look at key signature.  @code{#t} is `forever'."
   (and (pair? (car entry)) (cdddr entry)))
 
 (define (key-entry-alteration entry)
-  "Return the alteration of an entry in localKeySignature."
-  (if (number? (car entry))
-      (cdr entry)
-      (cadr entry)))
+  "Return the alteration of an entry in localKeySignature.
+
+For convenience, returns @code{0} if entry is @code{#f}."
+  (if entry
+      (if (number? (car entry))
+         (cdr entry)
+         (cadr entry))
+      0))
 
 (define-public (find-pitch-entry keysig pitch accept-global accept-local)
   "Return the first entry in @var{keysig} that matches @var{pitch}.
@@ -1174,9 +1184,7 @@ look at bar lines nor different accidentals at the same note name."
     (if (equal? #f entry)
        (cons #f #f)
        (let* ((global-entry (find-pitch-entry keysig pitch #t #f))
-              (key-acc (if (equal? global-entry #f)
-                           0
-                           (key-entry-alteration global-entry)))
+              (key-acc (key-entry-alteration global-entry))
               (acc (ly:pitch-alteration pitch))
               (entrymp (key-entry-measure-position entry))
               (entrybn (key-entry-bar-number entry)))
@@ -1192,9 +1200,7 @@ on the same staff line."
     (if (equal? #f entry)
        (cons #f #f)
        (let* ((global-entry (find-pitch-entry keysig pitch #f #f))
-              (key-acc (if (equal? global-entry #f)
-                           0
-                           (key-entry-alteration global-entry)))
+              (key-acc (key-entry-alteration global-entry))
               (acc (ly:pitch-alteration pitch))
               (entrymp (key-entry-measure-position entry))
               (entrybn (key-entry-bar-number entry)))
@@ -1378,6 +1384,36 @@ as a context."
        (ly:warning (_ "unknown accidental style: ~S") style)
        (make-sequential-music '()))))))
 
+(define-public (invalidate-alterations context)
+  "Invalidate alterations in @var{context}.
+
+Elements of @code{'localKeySignature} corresponding to local
+alterations of the key signature have the form
+@code{'((octave . notename) . (alter barnum . measurepos))}.
+Replace them with a version where @code{alter} is set to @code{'clef}
+to force a repetition of accidentals.
+
+Entries that conform with the current key signature are not invalidated."
+  (let* ((keysig (ly:context-property context 'keySignature)))
+    (set! (ly:context-property context 'localKeySignature)
+         (map-in-order
+          (lambda (entry)
+            (let* ((localalt (key-entry-alteration entry))
+                   (localoct (key-entry-octave entry)))
+              (if (or (accidental-voided? localalt)
+                      (not localoct)
+                      (= localalt
+                         (key-entry-alteration
+                          (find-pitch-entry
+                           keysig
+                           (ly:make-pitch localoct
+                                          (key-entry-notename entry)
+                                          0)
+                           #t #t))))
+                  entry
+                  (cons (car entry) (cons 'clef (cddr entry))))))
+          (ly:context-property context 'localKeySignature)))))
+                   
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define-public (skip-of-length mus)