]> git.donarmstrong.com Git - lilypond.git/commitdiff
''
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Sat, 20 Apr 2002 23:02:57 +0000 (23:02 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Sat, 20 Apr 2002 23:02:57 +0000 (23:02 +0000)
34 files changed:
ChangeLog
NEWS
lily/accidental-engraver.cc
lily/accidental-placement.cc [new file with mode: 0644]
lily/accidental.cc [new file with mode: 0644]
lily/axis-group-interface.cc
lily/include/align-interface.hh
lily/include/axis-group-interface.hh
lily/include/bar-line.hh
lily/include/bar.hh
lily/include/break-align-interface.hh
lily/include/breathing-sign.hh
lily/include/clef.hh
lily/include/local-key-item.hh
lily/include/multi-measure-rest.hh
lily/include/note-column.hh
lily/include/pitch.hh
lily/include/rest-collision.hh
lily/include/rhythmic-head.hh
lily/include/script.hh
lily/include/separating-group-spanner.hh
lily/include/skyline.hh [new file with mode: 0644]
lily/include/span-bar.hh
lily/include/staff-symbol-referencer.hh
lily/include/staff-symbol.hh
lily/include/stem-tremolo.hh
lily/include/system-start-delimiter.hh
lily/include/volta-bracket.hh
lily/local-key-item.cc
lily/new-accidental-engraver.cc [new file with mode: 0644]
lily/pitch.cc
lily/skyline.cc [new file with mode: 0644]
ly/engraver-init.ly
scm/grob-description.scm

index 88c06822af080a4b2e3a2dca3ea5673b84346296..14362a3a16f9cfc882308da2dc25523ef4729b47 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,27 @@
+2002-04-21  Han-Wen  <hanwen@cs.uu.nl>
+
+       * lily/include/accidental-placement.hh: new file.
+
+       * lily/accidental-placement.cc (alignment_callback): position
+       accidentals in a better way.
+
+       * lily/skyline.cc: new file. Compute distances for collections  of boxes. 
+
+       * lily/include/skyline.hh: new file
+
 2002-04-20  Han-Wen  <hanwen@cs.uu.nl>
 
+       * lily/accidental.cc (class Accidental_interface): grob for single
+       accidental.
+
+       * lily/accidental-engraver.cc (number_accidentals): Cleanups. Lots
+       of reformatting
+
+       * lily/new-accidental-engraver.cc (acknowledge_grob): Work
+       together with new accidental-interface. 
+
+       * lily/include/*.hh: remove spurious set_interface() decls.
+
        * lily/key-signature-interface.cc (brew_molecule): add padding for
        natural signs. Make natural typesetting like the sharp.
        
diff --git a/NEWS b/NEWS
index 4dd7ec9c36b5255189d35b74b2a35b462cc773da..70bc947d14e2f132dfd8a9a910a8281a2d949010 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -14,3 +14,5 @@ New features in 1.5
 * More ancient notation support.
 
 * Some entry optimizations.
+
+* Font updated and improved.
index 8a3110cfb68c494f773f50eba28856abdb57df32..6ee866df9b289a778f13b5985f60891cc88015a4 100644 (file)
 /**
 
 
-   FIXME: should not compute vertical positioning of accidentals, but
-   get them from the noteheads
+FIXME: should not compute vertical positioning of accidentals, but
+get them from the noteheads
 
-   The algorithm for accidentals should be documented, and made
-   tweakable.
+The algorithm for accidentals should be documented, and made
+tweakable.
 
 */
 
@@ -36,7 +36,7 @@
 struct Accidental_engraver : Engraver {
   Item *key_item_p_;
 protected:
-  TRANSLATOR_DECLARATIONS(Accidental_engraver);
+  TRANSLATOR_DECLARATIONS (Accidental_engraver);
   virtual void process_music ();
   virtual void acknowledge_grob (Grob_info);
   virtual void stop_translation_timestep ();
@@ -45,13 +45,20 @@ protected:
   virtual void finalize ();
 public:
 
-  // todo -> property   (why? -rz)
+  /*
+    TODO -> property.
+    
+    This is not a property, and it is not protected.  This poses a
+    very small risk of the value being GC'd from under us.
+
+    Oh well.
+  */
   SCM last_keysig_;
 
   /*
     Urgh. Since the accidentals depend on lots of variables, we have to
     store all information before we can really create the accidentals.
-   */
+  */
   Link_array<Grob> arpeggios_;
   
   Link_array<Note_req> mel_l_arr_;
@@ -65,7 +72,7 @@ public:
 
 Accidental_engraver::Accidental_engraver ()
 {
-  key_item_p_ =0;
+  key_item_p_ = 0;
   last_keysig_ = SCM_EOL;
 }
 
@@ -75,97 +82,126 @@ Accidental_engraver::initialize ()
   last_keysig_ = get_property ("keySignature");
 
   Translator_group * trans_ = daddy_trans_l_;
-  while (trans_) {
-    trans_ -> set_property ("localKeySignature",  ly_deep_copy(last_keysig_));
-    trans_ = trans_->daddy_trans_l_;
-  }
-  daddy_trans_l_->set_children_property("localKeySignature",last_keysig_);
-
+  while (trans_)
+    {
+      trans_ -> set_property ("localKeySignature",  ly_deep_copy (last_keysig_));
+      trans_ = trans_->daddy_trans_l_;
+    }
+  daddy_trans_l_->set_children_property ("localKeySignature", last_keysig_);
 }
 
-/** calculates the number of accidentals on basis of the current local key sig
-  * (passed as argument)
-  * Returns number of accidentals (0, 1 or 2).
-  *   Negative (-1 or -2) if accidental has changed.
-  **/
-// FIXME: Use references for SCM-values
+/*
+
+calculates the number of accidentals on basis of the current local key sig
+  (passed as argument)
+  Returns number of accidentals (0, 1 or 2).
+    Negative (-1 or -2) if accidental has changed.
+
+*/
 static int
-number_accidentals (SCM sig, Note_req * note_l, SCM curbarnum, SCM lazyness,
+number_accidentals (SCM sig, Note_req * note_l, SCM curbarnum, SCM lazyness, 
                    bool ignore_octave_b)
 {
   Pitch *pitch = unsmob_pitch (note_l->get_mus_property ("pitch"));
   int n = pitch->notename_i_;
   int o = pitch->octave_i_;
   int a = pitch->alteration_i_;
-  int curbarnum_i = gh_scm2int(curbarnum);
+  int curbarnum_i = gh_scm2int (curbarnum);
   int accbarnum_i = 0;
+
   SCM prev;
   if (ignore_octave_b)
     prev = ly_assoc_cdr (gh_int2scm (n), sig);
   else
     prev = gh_assoc (gh_cons (gh_int2scm (o), gh_int2scm (n)), sig);
-  /* should really be true unless prev==SCM_BOOL_F */
-  if(gh_pair_p(prev) && gh_pair_p(ly_cdr(prev))) {
-    accbarnum_i = gh_scm2int(ly_cddr(prev));
-    prev = gh_cons(ly_car(prev),ly_cadr(prev));
-  }
+
+  /* should really be true unless prev == SCM_BOOL_F */
+  if (gh_pair_p (prev) && gh_pair_p (ly_cdr (prev)))
+    {
+      accbarnum_i = gh_scm2int (ly_cddr (prev));
+      prev = gh_cons (ly_car (prev), ly_cadr (prev));
+    }
+  
   /* If an accidental was not found or the accidental was too old */
   if (prev == SCM_BOOL_F ||
-      (gh_number_p(lazyness) && curbarnum_i>accbarnum_i+gh_scm2int(lazyness)))
+      (gh_number_p (lazyness) && curbarnum_i > accbarnum_i + gh_scm2int (lazyness)))
     prev = gh_assoc (gh_int2scm (n), sig);
+
+
   SCM prev_acc = (prev == SCM_BOOL_F) ? gh_int2scm (0) : ly_cdr (prev);
 
   int p = gh_number_p (prev_acc) ? gh_scm2int (prev_acc) : 0;
 
   int num;
-  if (a==p && !to_boolean (note_l->get_mus_property ("force-accidental")) && gh_number_p(prev_acc)) num=0;
-  else if ( (abs(a)<abs(p) || p*a<0) && a!=0 ) num=2;
-  else num=1;
+  if (a == p
+      && !to_boolean (note_l->get_mus_property ("force-accidental"))
+      && gh_number_p (prev_acc))
+    num = 0;
+  else if ( (abs (a)<abs (p) || p*a<0) && a != 0 )
+    num = 2;
+  else
+    num = 1;
   
-  return a==p ? num : -num;
+  return a == p ? num : -num;
 }
 
-int
-number_accidentals (Note_req * note_l, Translator_group * origin_l,
-                   SCM accidentals_sl, SCM curbarnum_s) {
-  int number=0;
-  int diff=0;
-  if(gh_pair_p(accidentals_sl) && !gh_symbol_p(ly_car(accidentals_sl)))
-    warning(_f("Accidental typesetting list must begin with context-name: %s",
-              ly_scm2string(ly_car(accidentals_sl)).ch_C()));
-  while(gh_pair_p(accidentals_sl) && origin_l) {
-    // If pair then it is a new accidentals typesetting rule to be checked
-    if(gh_pair_p(ly_car(accidentals_sl))) {
-      SCM type = gh_caar(accidentals_sl);
-      SCM lazyness = gh_cdar(accidentals_sl);
-      SCM localsig = origin_l->get_property ("localKeySignature");
-      bool same_octave_b =
-       gh_eq_p(ly_symbol2scm("same-octave"),type);
-      bool any_octave_b =
-       gh_eq_p(ly_symbol2scm("any-octave"),type);
-      if(same_octave_b || any_octave_b) {
-       int n = number_accidentals
-         (localsig,note_l,curbarnum_s,lazyness,any_octave_b);
-       diff |= n<0;
-       number = max(number,abs(n));     
-      }
-      else warning(_f("unknown accidental typesetting: %s. Ignored",
-                     ly_symbol2string(type).ch_C()));
-    }
-    // if symbol then it is a context name. Scan parent contexts to find it.
-    else if (gh_symbol_p(ly_car(accidentals_sl))) {
-      String context = ly_symbol2string(ly_car(accidentals_sl));
-      while (origin_l && !origin_l->is_alias_b(context)) {
-        origin_l = origin_l->daddy_trans_l_;
-      }
-      if (!origin_l)
-       warning(_f("Symbol is not a parent context: %s. Ignored",
-                  context.ch_C()));
+static int
+number_accidentals (Note_req * note_l, Translator_group * origin_l, 
+                   SCM accidentals, SCM curbarnum)
+{
+  int number = 0;
+
+  bool diff = false;
+  if (gh_pair_p (accidentals) && !gh_symbol_p (ly_car (accidentals)))
+    warning (_f ("Accidental typesetting list must begin with context-name: %s", 
+                ly_scm2string (ly_car (accidentals)).ch_C ()));
+  
+  while (gh_pair_p (accidentals) && origin_l)
+    {
+      // If pair then it is a new accidentals typesetting rule to be checked
+      if (gh_pair_p (ly_car (accidentals)))
+       {
+         SCM type = gh_caar (accidentals);
+         SCM lazyness = gh_cdar (accidentals);
+         SCM localsig = origin_l->get_property ("localKeySignature");
+         
+         bool same_octave_b = 
+           gh_eq_p (ly_symbol2scm ("same-octave"), type);
+         bool any_octave_b = 
+           gh_eq_p (ly_symbol2scm ("any-octave"), type);
+
+         if (same_octave_b || any_octave_b)
+           {
+             int n = number_accidentals
+               (localsig, note_l, curbarnum, lazyness, any_octave_b);
+             diff = diff || (n < 0);
+             number = max (number, abs (n));     
+           }
+         else
+           warning (_f ("unknown accidental typesetting: %s. Ignored", 
+                        ly_symbol2string (type).ch_C ()));
+       }
+      
+
+      /*
+       if symbol then it is a context name. Scan parent contexts to find it.
+      */
+      else if (gh_symbol_p (ly_car (accidentals)))
+       {
+         String context = ly_symbol2string (ly_car (accidentals));
+         
+         while (origin_l && !origin_l->is_alias_b (context))
+           origin_l = origin_l->daddy_trans_l_;
+      
+         if (!origin_l)
+           warning (_f ("Symbol is not a parent context: %s. Ignored", 
+                        context.ch_C ()));
+       }
+      else warning (_f ("Accidental typesetting must be pair or context-name: %s", 
+                       ly_scm2string (ly_car (accidentals)).ch_C ()));
+      
+      accidentals = ly_cdr (accidentals);
     }
-    else warning(_f("Accidental typesetting must be pair or context-name: %s",
-                     ly_scm2string(ly_car(accidentals_sl)).ch_C()));
-    accidentals_sl = ly_cdr(accidentals_sl);
-  }
   return diff ? -number : number;
 }
 
@@ -175,46 +211,47 @@ Accidental_engraver::create_grobs ()
   if (!key_item_p_ && mel_l_arr_.size ()) 
     {
       //SCM localsig = get_property ("localKeySignature");
-      SCM accidentals_sl =  get_property ("autoAccidentals");
-      SCM cautionaries_sl =  get_property ("autoCautionaries");
+      SCM accidentals =  get_property ("autoAccidentals");
+      SCM cautionaries =  get_property ("autoCautionaries");
       SCM barnum = get_property ("currentBarNumber");
 
-      bool extra_natural_b = get_property ("extraNatural")==SCM_BOOL_T;
-      for (int i=0; i  < mel_l_arr_.size (); i++) 
+      bool extra_natural_b = get_property ("extraNatural") == SCM_BOOL_T;
+      for (int i = 0; i  < mel_l_arr_.size (); i++) 
        {
          Grob * support_l = head_l_arr_[i];
          Note_req * note_l = mel_l_arr_[i];
          Translator_group * origin_l = origin_l_arr_[i];
 
-         int num = number_accidentals(note_l,origin_l,accidentals_sl,barnum);
-         int num_caut = number_accidentals(note_l,origin_l,cautionaries_sl,barnum);
+         int num = number_accidentals (note_l, origin_l, accidentals, barnum);
+         int num_caut = number_accidentals (note_l, origin_l, cautionaries, barnum);
          bool cautionary = to_boolean (note_l->get_mus_property ("cautionary"));
-         if (abs(num_caut)>abs(num))
+         
+         if (abs (num_caut)>abs (num))
            {
-             num=num_caut;
-             cautionary=true;
+             num = num_caut;
+             cautionary = true;
            }
          
-         bool different=num<0;
-         num=abs(num);
+         bool different = num < 0;
+         num = abs (num);
 
          /* see if there's a tie that "changes" the accidental */
          /* works because if there's a tie, the note to the left
             is of the same pitch as the actual note */
 
-
          Grob *tie_break_reminder = 0;
          bool tie_changes = false;
-         for (int j=0; j < tie_l_arr_.size (); j++)
+         for (int j = 0; j < tie_l_arr_.size (); j++)
            if (support_l == Tie::head (tie_l_arr_[j], RIGHT))
              {
                tie_changes = different;
+
                /* Enable accidentals for broken tie
 
-                  We only want an accidental on a broken tie,
-                  if the tie changes the accidental.
+               We only want an accidental on a broken tie, 
+               if the tie changes the accidental.
                   
-                  Maybe check property noTieBreakForceAccidental? */
+               Maybe check property noTieBreakForceAccidental? */
                if (different)
                  tie_break_reminder = tie_l_arr_[j];
                break;
@@ -230,15 +267,15 @@ Accidental_engraver::create_grobs ()
                  if (gh_number_p (c0))
                    Staff_symbol_referencer::set_position (key_item_p_, gh_scm2int (c0));
                         
-                 announce_grob(key_item_p_, SCM_EOL);
+                 announce_grob (key_item_p_, SCM_EOL);
                }
 
              
-             Local_key_item::add_pitch (key_item_p_, *unsmob_pitch (note_l->get_mus_property ("pitch")),
-                                        cautionary,
-                                        num==2 && extra_natural_b,
+             Local_key_item::add_pitch (key_item_p_, *unsmob_pitch (note_l->get_mus_property ("pitch")), 
+                                        cautionary, 
+                                        num == 2 && extra_natural_b, 
                                         tie_break_reminder);
-             Side_position_interface::add_support (key_item_p_,support_l);
+             Side_position_interface::add_support (key_item_p_, support_l);
              
              support_l->set_grob_property ("accidentals-grob", key_item_p_->self_scm ());
            }
@@ -250,7 +287,7 @@ Accidental_engraver::create_grobs ()
 
            Checking whether it is tied also works mostly, but will it
            always do the correct thing?
-          */
+         */
          
          Pitch *pitch = unsmob_pitch (note_l->get_mus_property ("pitch"));
          int n = pitch->notename_i_;
@@ -260,33 +297,46 @@ Accidental_engraver::create_grobs ()
 
          /*
            TODO: Speed this up!
+           
            Perhaps only check translators mentioned in the auto-accidentals?
            -rz
+
+           TODO: profile this.
+           
+           I'd be surprised if the impact of this would be
+           measurable.  Anyway, it seems localsig doesn't change
+           every time-step, but a set_property() is done every
+           time. We could save on that, probably.
+
+           --hwn.
+           
+           
          */
          Translator_group * trans_ = origin_l_arr_[i];
-         while (trans_) {
-           SCM localsig = trans_->get_property ("localKeySignature");
-           if (tie_changes)
-             {
-               /*
-                 Remember an alteration that is different both from
-                 that of the tied note and of the key signature.
-               */
-               localsig = ly_assoc_front_x
-                 (localsig, on_s, gh_cons(SCM_BOOL_T,barnum));
-             }
-           else
-             {
-               /*
-                 not really really correct if there are more than one
-                 noteheads with the same notename.
-               */
-               localsig = ly_assoc_front_x
-                 (localsig, on_s, gh_cons(gh_int2scm (a),barnum)); 
-             }
-           trans_->set_property ("localKeySignature",  localsig);
-           trans_ = trans_->daddy_trans_l_;
-         }
+         while (trans_)
+           {
+             SCM localsig = trans_->get_property ("localKeySignature");
+             if (tie_changes)
+               {
+                 /*
+                   Remember an alteration that is different both from
+                   that of the tied note and of the key signature.
+                 */
+                 localsig = ly_assoc_front_x
+                   (localsig, on_s, gh_cons (SCM_BOOL_T, barnum));
+               }
+             else
+               {
+                 /*
+                   not really really correct if there are more than one
+                   noteheads with the same notename.
+                 */
+                 localsig = ly_assoc_front_x
+                   (localsig, on_s, gh_cons (gh_int2scm (a), barnum)); 
+               }
+             trans_->set_property ("localKeySignature",  localsig);
+             trans_ = trans_->daddy_trans_l_;
+           }
        }
     }
 
@@ -297,8 +347,8 @@ Accidental_engraver::create_grobs ()
        We add the accidentals to the support of the arpeggio, so it is put left of the
        accidentals. 
        
-       */
-      for (int i=0;  i < arpeggios_.size ();  i++)
+      */
+      for (int i = 0;  i < arpeggios_.size ();  i++)
        Side_position_interface::add_support (arpeggios_[i], key_item_p_);
 
       arpeggios_.clear ();
@@ -316,11 +366,11 @@ Accidental_engraver::stop_translation_timestep ()
 {
   if (key_item_p_)
     {
-      for (int i=0; i < head_l_arr_.size (); i++)
-       Side_position_interface::add_support (key_item_p_,head_l_arr_[i]);
+      for (int i = 0; i < head_l_arr_.size (); i++)
+       Side_position_interface::add_support (key_item_p_, head_l_arr_[i]);
 
       typeset_grob (key_item_p_);
-      key_item_p_ =0;
+      key_item_p_ = 0;
     }
 
 
@@ -357,38 +407,35 @@ Accidental_engraver::acknowledge_grob (Grob_info info)
 void
 Accidental_engraver::process_music ()
 {
-#if 0
-  SCM smp = get_property ("measurePosition");
-  Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
-#endif
-  
   SCM sig = get_property ("keySignature");
 
   /* Detect key sig changes.
      Update all parents and children
-     */
-  if (last_keysig_ != sig) {
-    Translator_group * trans_ = daddy_trans_l_;
-    while (trans_) {
-      trans_ -> set_property ("localKeySignature",  ly_deep_copy(sig));
-      trans_ = trans_->daddy_trans_l_;
-    }
-    daddy_trans_l_->set_children_property("localKeySignature",sig);
+  */
+  if (last_keysig_ != sig)
+    {
+      Translator_group * trans_ = daddy_trans_l_;
+      while (trans_)
+       {
+         trans_ -> set_property ("localKeySignature",  ly_deep_copy (sig));
+         trans_ = trans_->daddy_trans_l_;
+       }
+      daddy_trans_l_->set_children_property ("localKeySignature", sig);
 
-    last_keysig_ = sig;
-  }
+      last_keysig_ = sig;
+    }
 }
 
 
 
 
 
-ENTER_DESCRIPTION(Accidental_engraver,
-/* The FIXME below is deprecated and should be removed. -rz */
-/* descr */       "Make accidentals.  Catches note heads, ties and notices key-change
+ENTER_DESCRIPTION (Accidental_engraver,
+"Make accidentals.  Catches note heads, ties and notices key-change
 events.  Due to interaction with ties (which don't come together
-with note heads), this needs to be in a context higher than Tie_engraver. FIXME",
-/* creats*/       "Accidentals",
-/* acks  */       "rhythmic-head-interface tie-interface arpeggio-interface",
-/* reads */       "localKeySignature extraNatural autoAccidentals autoCautionaries",
-/* write */       "localKeySignature");
+with note heads), this needs to be in a context higher than Tie_engraver.",
+                  
+              "Accidentals",
+              "rhythmic-head-interface tie-interface arpeggio-interface",
+              "localKeySignature extraNatural autoAccidentals autoCautionaries",
+                  "localKeySignature");
diff --git a/lily/accidental-placement.cc b/lily/accidental-placement.cc
new file mode 100644 (file)
index 0000000..3d1179c
--- /dev/null
@@ -0,0 +1,166 @@
+/*   
+accidental-placement.cc --  implement Accidental_placement
+
+source file of the GNU LilyPond music typesetter
+
+(c) 2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+
+ */
+
+
+#include "item.hh"
+#include "skyline.hh"
+#include "music.hh"
+#include "pitch.hh"
+#include "warn.hh"
+#include "accidental-placement.hh"
+
+
+MAKE_SCHEME_CALLBACK(Accidental_placement,alignment_callback, 2);
+SCM
+Accidental_placement::alignment_callback(SCM s, SCM )
+{
+  Grob * me =unsmob_grob (s);
+
+  Grob * par = me->get_parent (X_AXIS);
+  if (!to_boolean (par->get_grob_property ("done")))
+  {
+    par->set_grob_property ("done", SCM_BOOL_T);
+    position_accidentals (par);
+  }
+  
+
+  return gh_int2scm (0);
+}
+
+void
+Accidental_placement::add_accidental (Grob* me, Grob* a)
+{
+  a->set_parent (me, X_AXIS);
+  a->add_offset_callback (alignment_callback_proc, X_AXIS);
+  SCM cause = a->get_parent (Y_AXIS)->get_grob_property("cause");
+
+  Music *mcause =unsmob_music (cause); 
+  if (!mcause)
+    {
+      programming_error ("Note head has no music cause!");
+      return; 
+    }
+
+  Pitch *p= unsmob_pitch (mcause->get_mus_property ("pitch"));
+
+  int n = p->notename_i_;
+
+  SCM accs = me->get_grob_property ("accidentals");
+  SCM key = gh_int2scm (n);
+  SCM entry = scm_assq (key, accs);
+  if (entry == SCM_BOOL_F)
+    {
+      entry = SCM_EOL;
+    }
+  else
+    entry = gh_cdr (entry);
+
+  entry = gh_cons (a->self_scm (), entry);
+
+  accs = scm_assq_set_x (accs,  key, entry);
+
+  me->set_grob_property ("accidentals", accs);
+}
+
+
+struct Accidental_placement_entry
+{
+  Array<Skyline_entry> left_skyline_;
+  Array<Skyline_entry> right_skyline_;
+  Interval vertical_extent_;
+  Array<Box> extents_;
+  Link_array<Grob> grobs_;
+  int notename_;
+};
+
+int ape_compare (Accidental_placement_entry *const &a,
+                Accidental_placement_entry *const &b)
+{
+  return sign (a->vertical_extent_.length () - b->vertical_extent_.length());
+}
+
+void
+Accidental_placement::position_accidentals (Grob * me)
+{
+  SCM accs = me->get_grob_property ("accidentals");
+
+  Link_array<Accidental_placement_entry> apes;
+  for (SCM s = accs; gh_pair_p (s); s =gh_cdr (s))
+    {
+      Accidental_placement_entry *ape = new Accidental_placement_entry;
+      ape->notename_ = gh_scm2int (gh_caar (s));
+      
+      for (SCM t = gh_cdar (s); gh_pair_p (t); t =gh_cdr (t))
+       ape->grobs_.push (unsmob_grob (gh_car (t)));
+
+      apes.push (ape);
+    }
+
+
+  Grob *commony =0 ;
+  for (int i= apes.size (); i--;)
+    for (int j = apes[i]->grobs_.size(); j--;)
+      {
+       Grob * a = apes[i]->grobs_[j];
+
+       if (commony)
+         commony =commony->common_refpoint (a, Y_AXIS);
+       else
+         commony =a;
+      }
+
+  for (int i= apes.size (); i--;)
+    {
+      Interval y ;
+      
+      for (int j = apes[i]->grobs_.size(); j--;)
+       {
+         Grob * a = apes[i]->grobs_[j];
+         Box b;
+         b[X_AXIS] = a->extent (me, X_AXIS);
+         b[Y_AXIS] = a->extent (commony, Y_AXIS);
+
+         y.unite (b[Y_AXIS]);
+         apes[i]->extents_.push (b);
+       }
+
+      apes[i]->vertical_extent_ = y;
+    }
+  
+  for (int i= apes.size (); i--;)
+    {
+      Accidental_placement_entry * ape = apes[i];
+      ape->left_skyline_ = extents_to_skyline (apes[i]->extents_, Y_AXIS, LEFT);
+      ape->right_skyline_ = extents_to_skyline (apes[i]->extents_, Y_AXIS, RIGHT);
+    }
+
+  apes.sort (&ape_compare);  
+
+  for (int i= apes.size ()-1; i-- > 0;)
+    {
+      Accidental_placement_entry *ape = apes[i];
+      Real here = 0.0;
+
+      Real d = skyline_meshing_distance (ape->right_skyline_, apes[i+1]->left_skyline_);
+
+      here += d;
+      for (int j  = ape->grobs_.size(); j--;)
+       {
+         ape->grobs_[j]->translate_axis (here, X_AXIS);
+       }
+    }
+
+  for (int i = apes.size(); i--;)
+    delete apes[i];
+}
+
+ADD_INTERFACE(Accidental_placement,
+             "accidental-placement-interface",
+             "Take care of complex accidental collisions.",
+             "accidentals done")
diff --git a/lily/accidental.cc b/lily/accidental.cc
new file mode 100644 (file)
index 0000000..44c26da
--- /dev/null
@@ -0,0 +1,70 @@
+#include "font-interface.hh"
+#include "item.hh"
+#include "molecule.hh"
+
+class Accidental_interface
+{
+public:
+  DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM));
+  static bool has_interface (Grob*);
+};
+
+Molecule
+parenthesize (Grob*me, Molecule m)
+{
+  Molecule open = Font_interface::get_default_font (me)->find_by_name (String ("accidentals-leftparen"));
+  Molecule close = Font_interface::get_default_font (me)->find_by_name (String ("accidentals-rightparen"));
+  m.add_at_edge (X_AXIS, LEFT, Molecule (open), 0);
+  m.add_at_edge (X_AXIS, RIGHT, Molecule (close), 0);
+
+  return m;
+}
+
+MAKE_SCHEME_CALLBACK (Accidental_interface,brew_molecule,1);
+SCM
+Accidental_interface::brew_molecule (SCM smob)
+{
+  Grob *me = unsmob_grob (smob);
+
+  SCM scm_style = me->get_grob_property ("style");
+  String style;
+  if (gh_symbol_p (scm_style))
+    {
+      style = ly_scm2string (scm_symbol_to_string (scm_style));
+    }
+  else
+    {
+      /*
+       preferably no name for the default style.
+       */
+      style = "";
+    }
+
+  
+  Molecule mol;
+  for (SCM s = me->get_grob_property ("accidentals");
+       gh_pair_p (s);  s= gh_cdr (s))
+    {
+      SCM entry  = gh_car (s);
+      
+      
+      Molecule acc (Font_interface::get_default_font (me)->
+                   find_by_name (String ("accidentals-") +
+                                 style +
+                                 to_str (gh_scm2int(entry))));
+      
+      mol.add_at_edge (X_AXIS,  RIGHT, acc, 0.0);
+    }
+
+  if (to_boolean (me->get_grob_property ("parenthesize")))
+    mol = parenthesize (me, mol); 
+  
+  return mol.smobbed_copy();
+}
+
+
+
+ADD_INTERFACE(Accidental_interface, "accidental-interface",
+             "a single accidental",
+             "accidentals parenthesize");
index 10ffa7172a33835cd7af49543c402ee295c3c196..424eb533306b7992350bb1dd918dcdf7d4ed8143 100644 (file)
@@ -75,7 +75,6 @@ Axis_group_interface::group_extent_callback (SCM element_smob, SCM scm_axis)
 void
 Axis_group_interface::set_axes (Grob*me,Axis a1, Axis a2)
 {
-  // set_interface () ?
   SCM sa1= gh_int2scm (a1);
   SCM sa2 = gh_int2scm (a2);
 
index b2ebee3b7df1d7ac62f5795b10a2cf69a9d43146..d88898c17615618d4166a849c36f97e52ca7e57b 100644 (file)
@@ -23,7 +23,7 @@ struct Align_interface {
   static Axis axis (Grob*) ;
   static void add_element (Grob*,Grob*, SCM callback);
   static int get_count (Grob*,Grob*);
-  static void set_interface (Grob*);
+
   static bool has_interface (Grob*);
 };
 
index ed9f991cfb508643b86ef78e497b8255c72e5e37..e990d2e7382a974f6f3a657908bcbcaee1f811e8 100644 (file)
@@ -25,7 +25,7 @@ struct Axis_group_interface
   static bool axis_b (Grob*,Axis);
   static Link_array<Grob> get_children (Grob*);
   static bool has_interface (Grob*);
-  static void set_interface (Grob*);
+  
   
 };
 
index d0bb69c9c92b35252108c3ef7e69d61c2b122cc0..4b747f95f17726c06b0e568e494143b2f8e34f60 100644 (file)
@@ -17,7 +17,7 @@ class Bar_line
 {
 public:
   static bool has_interface (Grob*);
-  static void set_interface (Grob*);
+  
   static Molecule compound_barline (Grob*, String, Real height) ;
   static Molecule simple_barline (Grob*, Real wid, Real height) ;      
   DECLARE_SCHEME_CALLBACK (get_staff_bar_size, (SCM ));
index 5132040ae71903c5c3235dace93866bc31cce12e..6b5acda293a6d624a5b1312be24bca768758856b 100644 (file)
@@ -17,7 +17,7 @@ class Bar
 {
 public:
   static bool has_interface (Grob*);
-  static void set_interface (Grob*);
+  
   static Molecule compound_barline (Grob*, String, Real height) ;
   static Molecule simple_barline (Grob*, Real wid, Real height) ;      
   DECLARE_SCHEME_CALLBACK (get_staff_bar_size, (SCM ));
index cd0cf144c79c1e2c1142d4d2a0095028e822a47c..41aa1cc486e8389bf37d539dcf15e004f0fb0675 100644 (file)
@@ -17,7 +17,7 @@ class Break_align_interface
 public:
   static void do_alignment (Grob*);
   static void new_do_alignment (Grob*);  
-  static void set_interface (Grob*);
+  
   static bool has_interface (Grob*);
   static void add_element (Grob*me, Grob*add);
   DECLARE_SCHEME_CALLBACK (alignment_callback, (SCM element, SCM axis));
index f9a7a77887f889c4fb6aa2b0dd31e81b4353378c..96a99de9922583b277caa71567124167c40efac4 100644 (file)
@@ -21,7 +21,7 @@ class Breathing_sign
 public:
   DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM ));
   DECLARE_SCHEME_CALLBACK (offset_callback, (SCM element, SCM axis));
-  static void set_interface (Grob*);
+  
   static bool has_interface (Grob*);
 };
 
index 7885205e7e7a6ff68da84931db92765f295390e3..0f0d4f0ce9e625828fa5bea2759658a1db2324f9 100644 (file)
@@ -17,7 +17,7 @@ struct Clef
   DECLARE_SCHEME_CALLBACK (before_line_breaking, (SCM ));
   DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM ));
   static bool has_interface (Grob*);
-  static void set_interface (Grob*);
+  
 };
 
 
index 8a2dd3199c1c982ddbd016c68fbc6bfc77b954f6..99bfbd135eac9f6110bbe2cfcbc7ced6a750e1a7 100644 (file)
@@ -19,7 +19,6 @@ public:
   DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM));
   static void add_pitch (Grob*me, Pitch, bool cautionary, bool natural, Grob *tie_break_cautionary);
   static bool has_interface (Grob*);
-  static void set_interface (Grob*);  
 };
 
 
index 3ba796c515131eba49b518ccfbadc2075f7b0de8..2b73ba384e259f9b70b870478dfda6cfdc34436b 100644 (file)
@@ -17,7 +17,7 @@
 class Multi_measure_rest
 {
 public:
-  static void set_interface (Grob*);
+  
   static bool has_interface (Grob*);
   DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM ));
   DECLARE_SCHEME_CALLBACK (percent, (SCM));
index 6ec04c2ee616461a162186ab7e7dc10765a04058..72790486601dce56caf1fe33417a296feefc9bb2 100644 (file)
@@ -40,7 +40,7 @@ public:
   static void add_head (Grob*me,Grob*);
   static bool rest_b (Grob*me);
   static bool has_interface (Grob*);
-  static void set_interface (Grob*);
+  
   static Item *stem_l (Grob*);
 };
 
index 0d30f0529fa77f5544589dc6316c0f98f775b159..d734189314ad686305e724bfb9c7fedf9770a80b 100644 (file)
@@ -78,6 +78,7 @@ DECLARE_UNSMOB(Pitch,pitch);
 INSTANTIATE_COMPARE (Pitch, Pitch::compare);
 
 int compare (Array<Pitch>*, Array<Pitch>*);
+extern SCM pitch_less_proc;
 
 #endif /* MUSICAL_PITCH_HH */
 
index 343c0e1cdd697ca316a5ac8f84f75be389aea33e..b49e58dbc4bfbd67e9f1e4822d74753210e2f120 100644 (file)
@@ -20,7 +20,7 @@ class Rest_collision
 {
 public:
   static void add_column (Grob*me,Grob*);
-  static void set_interface (Grob*me);
+  
   static bool has_interface (Grob*);
   DECLARE_SCHEME_CALLBACK (force_shift_callback, (SCM element, SCM axis));
   static SCM do_shift (Grob*,SCM);
index 7cb64250ca970ea4ca878351f3940a34c4f3b67f..af4af02ae8838d906996470fe433ac1bc3748626 100644 (file)
@@ -23,7 +23,7 @@ public:
   static int dot_count (Grob*) ;
   DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM ));
   static bool has_interface (Grob*);
-  static void set_interface (Grob*);
+  
 };
 
 #endif // RHYTHMIC_HEAD_HH
index d2d10b8f7912be079cf71f3b9f2e959763fd11a9..41b7654b08ef30063fbb6cd1f449cedfcf353a12 100644 (file)
@@ -22,7 +22,7 @@ class Script
 {
 public:
   static Molecule get_molecule (Grob*,Direction d);
-  static void set_interface (Grob*);
+  
   static bool  has_interface (Grob*);
   DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM ));
   DECLARE_SCHEME_CALLBACK (before_line_breaking, (SCM ));
index 38f0e8928814cb5b5a3ccda6b33c4aa3a4a9823d..37256f0310e596f701604c352cf03b6c790f44bf 100644 (file)
@@ -17,7 +17,7 @@ class Separating_group_spanner
 public:
   static void add_spacing_unit (Grob*me, Item*);
   static void find_rods (Item*, SCM);
-  static void set_interface (Grob*);
+  
   static bool has_interface (Grob*);
   static void find_musical_sequences (Grob*);
   DECLARE_SCHEME_CALLBACK (set_spacing_rods, (SCM ));
diff --git a/lily/include/skyline.hh b/lily/include/skyline.hh
new file mode 100644 (file)
index 0000000..0a477b8
--- /dev/null
@@ -0,0 +1,34 @@
+/*   
+  skyline.hh -- declare Skyline_entry and funcbs.
+
+  source file of the GNU LilyPond music typesetter
+
+  (c) 2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+*/
+
+#ifndef SKYLINE_HH
+#define SKYLINE_HH
+
+#include "array.hh"
+#include "box.hh"
+
+struct Skyline_entry
+{
+  Interval width_;
+  Real height_;
+  Skyline_entry();
+  Skyline_entry (Interval, Real);
+};
+
+void
+insert_extent_into_skyline (Array<Skyline_entry> *line, Box b, Axis line_axis,
+                           Direction d);
+Array<Skyline_entry>
+extents_to_skyline (Array<Box> extents, Axis a, Direction d);
+Real
+skyline_meshing_distance (Array<Skyline_entry> buildings,
+                         Array<Skyline_entry> clouds);
+
+
+#endif /* SKYLINE_HH */
+
index a6cd7960d1e02a7271efbd8c84d5634caa4dfb4b..56f4d2a0e5c4c47f98dabc09accce14176431280 100644 (file)
@@ -21,7 +21,7 @@
 class Span_bar
 {
 public:
-  static void set_interface (Grob*);
+  
   static bool has_interface (Grob*);  
   static Interval get_spanned_interval (Grob*);
   static void add_bar (Grob*,Grob*);
index c250e9e0d42c442e30fe0e536afda9c55f3f95ff..531497d98890cc10370f226f4e4558502f7f9c54 100644 (file)
@@ -21,7 +21,7 @@
 class Staff_symbol_referencer 
 {
 public:
-  static void set_interface (Grob*);
+  
   static bool has_interface (Grob*);
   static bool ugly_hack (Grob*);  
   static void set_position (Grob*,Real);
index 4043069cbf469ad8552ab4a3f08b42c6605736d1..497b7472fe230725d94852d548f5b63908fdc636 100644 (file)
@@ -24,6 +24,6 @@ public:
   static int line_count (Grob*);
   DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM ));
   static bool has_interface (Grob*);
-  static void set_interface (Grob*);
+  
 };
 #endif // STAFF_SYMBOL_HH
index 1a6d9248e8e865d82bcc2e8d4193c1b92519fc33..781d575016e2490496c9facbea5e5d1405c60c11 100644 (file)
@@ -16,7 +16,7 @@
 class Stem_tremolo
 {
 public:
-  static void set_interface (Grob*);
+  
   static bool has_interface (Grob*);
   DECLARE_SCHEME_CALLBACK (dim_callback, (SCM smob, SCM axis));
   DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM ));
index 88ee130d2e3809f153597ffa5196d2cf2e94acf1..9765951fedb683e94712580d68ad267fb2c7885d 100644 (file)
@@ -21,7 +21,7 @@ class System_start_delimiter
 public:
   DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM ));
   
-  static void set_interface (Grob*me);
+  
   static bool has_interface (Grob*);
   DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM ));
   static void try_collapse (Grob*);
index fda29658e8eb37268a345102f3e36c440830e59e..6beb4e05fdf6262740d42f56ae3a2910fddc9302 100644 (file)
@@ -14,9 +14,7 @@
 class Volta_bracket_interface
 {
 public:
-  static void set_interface (Grob*);
   static bool has_interface (Grob*);
-  
   DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM ));
   static void add_column (Grob*, Grob*col);
   static void add_bar (Grob*me, Item*bar);
index 15c2e9ec28397df40bdaee2f8415c0ab4b6f58c5..1014a232e7b4d6960b38c3ed8be2721109d7ea02 100644 (file)
 #include "tie.hh"
 #include "lookup.hh"
 
-static SCM
-pitch_less (SCM p1, SCM p2)
-{
-  return Pitch::less_p (ly_car (p1),  ly_car (p2));
-}
-
-static SCM pitch_less_proc;
-
-void
-init_pitch_funcs ()
-{
-  pitch_less_proc = gh_new_procedure2_0 ("pitch-less", &pitch_less);
-}
-
-ADD_SCM_INIT_FUNC (lkpitch,init_pitch_funcs);
 
 
 void
@@ -172,7 +157,6 @@ Local_key_item::brew_molecule (SCM smob)
          oct_b = true; 
        }
       
-
       lastoct = p.octave_i () ;
 
       bool cautionary = (scm_memq (ly_symbol2scm ("cautionary"), opts) != SCM_BOOL_F);
@@ -181,7 +165,6 @@ Local_key_item::brew_molecule (SCM smob)
       int frs = (gh_exact_p(font_rel_siz) ? gh_scm2int(font_rel_siz) : 0);
       int cs = (gh_exact_p(caut_siz) ? gh_scm2int(caut_siz) : 0);
 
-
       // Ugh. This will only work if only called once on each grob. --rz
       if (cautionary && caut_siz!=0)
        me->set_grob_property ("font-relative-size",gh_int2scm(frs+cs));
diff --git a/lily/new-accidental-engraver.cc b/lily/new-accidental-engraver.cc
new file mode 100644 (file)
index 0000000..a8918d0
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+  accidental-engraver.cc -- implement accidental_engraver
+
+  (c)  1997--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  Modified 2001-2002 by Rune Zedeler <rz@daimi.au.dk>
+*/
+
+#include "musical-request.hh"
+#include "command-request.hh"
+#include "local-key-item.hh"
+#include "item.hh"
+#include "tie.hh"
+#include "rhythmic-head.hh"
+#include "engraver-group-engraver.hh"
+#include "accidental-placement.hh"
+#include "side-position-interface.hh"
+#include "engraver.hh"
+#include "arpeggio.hh"
+#include "warn.hh"
+
+#include "translator-group.hh"
+
+/**
+
+
+FIXME: should not compute vertical positioning of accidentals, but
+get them from the noteheads
+
+The algorithm for accidentals should be documented, and made
+tweakable.
+
+*/
+
+struct Accidental_entry {
+  bool done_;
+  Note_req * melodic_;
+  Grob * accidental_;
+  Translator_group *origin_;
+  Grob*  head_;
+  Accidental_entry();
+};
+
+Accidental_entry::Accidental_entry()
+{
+  done_ = false;
+  melodic_ =0;
+  accidental_ = 0;
+  origin_ = 0;
+  head_ = 0;
+}
+
+struct New_accidental_engraver : Engraver {
+protected:
+  TRANSLATOR_DECLARATIONS (New_accidental_engraver);
+  virtual void process_music ();
+  virtual void acknowledge_grob (Grob_info);
+  virtual void stop_translation_timestep ();
+  virtual void initialize ();
+  virtual void create_grobs ();
+  virtual void finalize ();
+public:
+
+  /*
+    TODO -> property.
+    
+    This is not a property, and it is not protected.  This poses a
+    very small risk of the value being GC'd from under us.
+
+    Oh well.
+  */
+  SCM last_keysig_;
+
+  /*
+    Urgh. Since the accidentals depend on lots of variables, we have to
+    store all information before we can really create the accidentals.
+  */
+  Link_array<Grob> arpeggios_;
+
+  Grob * accidental_placement_;
+  
+
+  /*
+    The next 
+   */
+  Array<Accidental_entry> accidental_arr_;
+  
+  Link_array<Grob> tie_arr_;
+
+
+};
+
+
+New_accidental_engraver::New_accidental_engraver ()
+{
+  accidental_placement_ = 0;
+  last_keysig_ = SCM_EOL;
+}
+
+void
+New_accidental_engraver::initialize ()
+{
+  last_keysig_ = get_property ("keySignature");
+
+  Translator_group * trans_ = daddy_trans_l_;
+  while (trans_)
+    {
+      trans_ -> set_property ("localKeySignature",  ly_deep_copy (last_keysig_));
+      trans_ = trans_->daddy_trans_l_;
+    }
+  daddy_trans_l_->set_children_property ("localKeySignature", last_keysig_);
+}
+
+/*
+
+calculates the number of accidentals on basis of the current local key sig
+  (passed as argument)
+  Returns number of accidentals (0, 1 or 2).
+    Negative (-1 or -2) if accidental has changed.
+
+*/
+static int
+number_accidentals (SCM sig, Note_req * note_l, Pitch *pitch, SCM curbarnum, SCM lazyness, 
+                   bool ignore_octave_b)
+{
+  int n = pitch->notename_i_;
+  int o = pitch->octave_i_;
+  int a = pitch->alteration_i_;
+  int curbarnum_i = gh_scm2int (curbarnum);
+  int accbarnum_i = 0;
+
+  SCM prev;
+  if (ignore_octave_b)
+    prev = ly_assoc_cdr (gh_int2scm (n), sig);
+  else
+    prev = gh_assoc (gh_cons (gh_int2scm (o), gh_int2scm (n)), sig);
+
+  /* should really be true unless prev == SCM_BOOL_F */
+  if (gh_pair_p (prev) && gh_pair_p (ly_cdr (prev)))
+    {
+      accbarnum_i = gh_scm2int (ly_cddr (prev));
+      prev = gh_cons (ly_car (prev), ly_cadr (prev));
+    }
+  
+  /* If an accidental was not found or the accidental was too old */
+  if (prev == SCM_BOOL_F ||
+      (gh_number_p (lazyness) && curbarnum_i > accbarnum_i + gh_scm2int (lazyness)))
+    prev = gh_assoc (gh_int2scm (n), sig);
+
+
+  SCM prev_acc = (prev == SCM_BOOL_F) ? gh_int2scm (0) : ly_cdr (prev);
+
+  int p = gh_number_p (prev_acc) ? gh_scm2int (prev_acc) : 0;
+
+  int num;
+  if (a == p
+      && !to_boolean (note_l->get_mus_property ("force-accidental"))
+      && gh_number_p (prev_acc))
+    num = 0;
+  else if ( (abs (a)<abs (p) || p*a<0) && a != 0 )
+    num = 2;
+  else
+    num = 1;
+  
+  return a == p ? num : -num;
+}
+
+static int
+number_accidentals (Note_req * note_l, Pitch *pitch, Translator_group * origin_l, 
+                   SCM accidentals, SCM curbarnum)
+{
+  int number = 0;
+
+  bool diff = false;
+  if (gh_pair_p (accidentals) && !gh_symbol_p (ly_car (accidentals)))
+    warning (_f ("Accidental typesetting list must begin with context-name: %s", 
+                ly_scm2string (ly_car (accidentals)).ch_C ()));
+  
+  while (gh_pair_p (accidentals) && origin_l)
+    {
+      // If pair then it is a new accidentals typesetting rule to be checked
+      if (gh_pair_p (ly_car (accidentals)))
+       {
+         SCM type = gh_caar (accidentals);
+         SCM lazyness = gh_cdar (accidentals);
+         SCM localsig = origin_l->get_property ("localKeySignature");
+         
+         bool same_octave_b = 
+           gh_eq_p (ly_symbol2scm ("same-octave"), type);
+         bool any_octave_b = 
+           gh_eq_p (ly_symbol2scm ("any-octave"), type);
+
+         if (same_octave_b || any_octave_b)
+           {
+             int n = number_accidentals
+               (localsig, note_l, pitch, curbarnum, lazyness, any_octave_b);
+             diff = diff || (n < 0);
+             number = max (number, abs (n));     
+           }
+         else
+           warning (_f ("unknown accidental typesetting: %s. Ignored", 
+                        ly_symbol2string (type).ch_C ()));
+       }
+      
+
+      /*
+       if symbol then it is a context name. Scan parent contexts to find it.
+      */
+      else if (gh_symbol_p (ly_car (accidentals)))
+       {
+         String context = ly_symbol2string (ly_car (accidentals));
+         
+         while (origin_l && !origin_l->is_alias_b (context))
+           origin_l = origin_l->daddy_trans_l_;
+      
+         if (!origin_l)
+           warning (_f ("Symbol is not a parent context: %s. Ignored", 
+                        context.ch_C ()));
+       }
+      else warning (_f ("Accidental typesetting must be pair or context-name: %s", 
+                       ly_scm2string (ly_car (accidentals)).ch_C ()));
+      
+      accidentals = ly_cdr (accidentals);
+    }
+  return diff ? -number : number;
+}
+
+void
+New_accidental_engraver::create_grobs ()
+{
+  if (accidental_arr_.size () && !accidental_arr_.top().done_)
+    {
+      //SCM localsig = get_property ("localKeySignature");
+      SCM accidentals =  get_property ("autoAccidentals");
+      SCM cautionaries =  get_property ("autoCautionaries");
+      SCM barnum = get_property ("currentBarNumber");
+
+      bool extra_natural_b = get_property ("extraNatural") == SCM_BOOL_T;
+      for (int i = 0; i  < accidental_arr_.size (); i++) 
+       {
+         if (accidental_arr_[i].done_ )
+           continue;
+         accidental_arr_[i].done_  = true;
+         Grob * support_l = accidental_arr_[i].head_;
+         Note_req * note_l = accidental_arr_[i].melodic_;
+         Translator_group * origin_l = accidental_arr_[i].origin_;
+
+         Pitch * pitch = unsmob_pitch (note_l->get_mus_property ("pitch"));
+         int num = number_accidentals (note_l, pitch, origin_l, accidentals, barnum);
+         int num_caut = number_accidentals (note_l, pitch, origin_l, cautionaries, barnum);
+         bool cautionary = to_boolean (note_l->get_mus_property ("cautionary"));
+         
+         if (abs (num_caut) > abs (num))
+           {
+             num = num_caut;
+             cautionary = true;
+           }
+         
+         bool different = num < 0;
+         num = abs (num);
+
+         /* see if there's a tie that "changes" the accidental */
+         /* works because if there's a tie, the note to the left
+            is of the same pitch as the actual note */
+
+         Grob *tie_break_reminder = 0;
+         bool tie_changes = false;
+         for (int j = 0; j < tie_arr_.size (); j++)
+           if (support_l == Tie::head (tie_arr_[j], RIGHT))
+             {
+               tie_changes = different;
+
+               /* Enable accidentals for broken tie
+
+               We only want an accidental on a broken tie, 
+               if the tie changes the accidental.
+                  
+               Maybe check property noTieBreakForceAccidental? */
+               if (different)
+                 tie_break_reminder = tie_arr_[j];
+               break;
+             }
+
+         if (num)
+           {
+             Grob * a = new Item (get_property ("Accidental"));
+             a->set_parent (support_l, Y_AXIS);
+
+             if (!accidental_placement_)
+               {
+                 accidental_placement_ = new Item (get_property ("AccidentalPlacement"));
+                 announce_grob (accidental_placement_, a->self_scm());
+               }
+             
+             Accidental_placement::add_accidental (accidental_placement_, a);
+             
+             Side_position_interface::add_support (a, support_l);
+             announce_grob (a, SCM_EOL);
+
+             // todo: add cautionary option
+             SCM accs = gh_cons (gh_int2scm (pitch->alteration_i_), SCM_EOL);
+             if (num == 2 && extra_natural_b)
+               accs = gh_cons (gh_int2scm (0), accs);
+
+             if (tie_break_reminder)
+               ;               // TODO.
+             support_l->set_grob_property ("accidentals-grob", a->self_scm ());
+
+             a->set_grob_property ("accidentals", accs);
+             accidental_arr_[i].accidental_ = a;
+ /*
+       We add the accidentals to the support of the arpeggio, so it is put left of the
+       accidentals. 
+       
+      */
+             for (int i = 0;  i < arpeggios_.size ();  i++)
+               Side_position_interface::add_support (arpeggios_[i], a);
+           }
+         
+
+         /*
+           We should not record the accidental if it is the first
+           note and it is tied from the previous measure.
+
+           Checking whether it is tied also works mostly, but will it
+           always do the correct thing?
+         */
+         
+
+         int n = pitch->notename_i_;
+         int o = pitch->octave_i_;
+         int a = pitch->alteration_i_;
+         SCM on_s = gh_cons (gh_int2scm (o), gh_int2scm (n));
+
+         /*
+           TODO: Speed this up!
+           
+           Perhaps only check translators mentioned in the auto-accidentals?
+           -rz
+
+           TODO: profile this.
+           
+           I'd be surprised if the impact of this would be
+           measurable.  Anyway, it seems localsig doesn't change
+           every time-step, but a set_property() is done every
+           time. We could save on that, probably.
+
+           --hwn.
+           
+           
+         */
+
+         while (origin_l)
+           {
+             SCM localsig = origin_l->get_property ("localKeySignature");
+             if (tie_changes)
+               {
+                 /*
+                   Remember an alteration that is different both from
+                   that of the tied note and of the key signature.
+                 */
+                 localsig = ly_assoc_front_x
+                   (localsig, on_s, gh_cons (SCM_BOOL_T, barnum));
+               }
+             else
+               {
+                 /*
+                   not really really correct if there are more than one
+                   noteheads with the same notename.
+                 */
+                 localsig = ly_assoc_front_x
+                   (localsig, on_s, gh_cons (gh_int2scm (a), barnum)); 
+               }
+             origin_l->set_property ("localKeySignature",  localsig);
+             origin_l = origin_l->daddy_trans_l_;
+           }
+       }
+    }
+}
+
+void
+New_accidental_engraver::finalize ()
+{
+
+}
+
+void
+New_accidental_engraver::stop_translation_timestep ()
+{
+  for (int i = 0; i < accidental_arr_.size(); i++)
+    {
+      Grob *a = accidental_arr_[i].accidental_;
+      if (a)
+       {
+         typeset_grob (a);
+       }
+    }
+
+  if (accidental_placement_)
+    typeset_grob(accidental_placement_);
+  accidental_placement_ = 00;
+  
+  accidental_arr_.clear();
+  arpeggios_.clear ();
+  tie_arr_.clear ();
+}
+
+void
+New_accidental_engraver::acknowledge_grob (Grob_info info)
+{
+  Note_req * note_l =  dynamic_cast <Note_req *> (info.music_cause ());
+
+  if (note_l && Rhythmic_head::has_interface (info.grob_l_))
+    {
+      Accidental_entry entry ;
+      entry.head_ = info.grob_l_;
+      entry.origin_ = info.origin_trans_l_->daddy_trans_l_;
+      entry.melodic_ = note_l;
+
+      accidental_arr_.push (entry);
+    }
+  else if (Tie::has_interface (info.grob_l_))
+    {
+      tie_arr_.push (info.grob_l_);
+    }
+  else if (Arpeggio::has_interface (info.grob_l_))
+    {
+      arpeggios_.push (info.grob_l_); 
+    }
+  
+}
+
+void
+New_accidental_engraver::process_music ()
+{
+  SCM sig = get_property ("keySignature");
+
+  /* Detect key sig changes.
+     Update all parents and children
+  */
+  if (last_keysig_ != sig)
+    {
+      Translator_group * trans_ = daddy_trans_l_;
+      while (trans_)
+       {
+         trans_ -> set_property ("localKeySignature",  ly_deep_copy (sig));
+         trans_ = trans_->daddy_trans_l_;
+       }
+      daddy_trans_l_->set_children_property ("localKeySignature", sig);
+
+      last_keysig_ = sig;
+    }
+}
+
+
+
+
+
+ENTER_DESCRIPTION (New_accidental_engraver,
+"Make accidentals.  Catches note heads, ties and notices key-change
+events.  Due to interaction with ties (which don't come together
+with note heads), this needs to be in a context higher than Tie_engraver.",
+                  
+              "Accidental",
+              "rhythmic-head-interface tie-interface arpeggio-interface",
+              "localKeySignature extraNatural autoAccidentals autoCautionaries",
+                  "localKeySignature");
index f5fe945f997d7e24c0de7dae0bd96a6bfab9b21d..8bcfcb4e3a5d53b3385e567cc8396c0724b3fda8 100644 (file)
@@ -348,6 +348,13 @@ pitch_semitones (SCM pp)
 
   return gh_int2scm (q);
 }
+SCM pitch_less_proc;
+static SCM
+pitch_less (SCM p1, SCM p2)
+{
+  return Pitch::less_p (ly_car (p1),  ly_car (p2));
+}
+
 
 static void
 add_funcs ()
@@ -359,6 +366,7 @@ add_funcs ()
   scm_c_define_gsubr ("pitch-alteration", 1, 0, 0, (Scheme_function_unknown)pitch_alteration);
   scm_c_define_gsubr ("pitch-semitones", 1, 0, 0, (Scheme_function_unknown)pitch_semitones);
   scm_c_define_gsubr ("Pitch::transpose", 2, 0, 0, (Scheme_function_unknown) pitch_transpose);
+  pitch_less_proc = gh_new_procedure2_0 ("pitch-less", &pitch_less);
 }
 
 ADD_SCM_INIT_FUNC (pitch, add_funcs);
@@ -387,3 +395,4 @@ Pitch::alteration_i () const
 {
   return alteration_i_;
 }
+
diff --git a/lily/skyline.cc b/lily/skyline.cc
new file mode 100644 (file)
index 0000000..d010bf4
--- /dev/null
@@ -0,0 +1,116 @@
+/*   
+  skyline.cc -- implement Skyline_entry and funcs.
+
+  source file of the GNU LilyPond music typesetter
+
+  (c) 2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+*/
+
+#include "skyline.hh" 
+
+void
+insert_extent_into_skyline (Array<Skyline_entry> *line, Box b, Axis line_axis,
+                           Direction d)
+{
+  Interval extent = b[line_axis];
+  if (extent.empty_b())
+    return;
+  
+  Real stick_out = b[other_axis (line_axis)][d];
+  
+  for (int i = line->size(); i--;)
+    {
+      Interval w = line->elem(i).width_;
+      if (extent[LEFT] > w[RIGHT])
+       break;
+      
+      w.intersect (extent);
+      Real my_height = line->elem(i).height_;
+
+      if (!w.empty_b () && d* (my_height - stick_out) < 0)
+       {
+         Interval e1 (line->elem(i).width_[LEFT], extent[LEFT]);
+         Interval e3 (extent[RIGHT], line->elem(i).width_[RIGHT]);
+
+         if (!e3.empty_b ())
+           line->insert (Skyline_entry (e3, my_height), i+1);
+
+         line->elem_ref(i).height_ = stick_out;
+         line->elem_ref(i).width_ = w;
+         if (!e1.empty_b ())
+           line->insert (Skyline_entry (e1, my_height), i );
+       }
+
+
+    }
+}
+
+Array<Skyline_entry>
+extents_to_skyline (Array<Box> extents, Axis a, Direction d)
+{
+  Array<Skyline_entry> skyline;
+
+  Interval i;
+  i.set_empty();
+  i.swap();
+  Skyline_entry e;
+  e.width_ = i;
+  e.height_ = -d * infinity_f; 
+  skyline.push (e);
+
+  /*
+    This makes a quadratic algorithm -- we could do better (n log (n) ) but that
+    seems overkill for now.
+   */
+  for (int j = extents.size(); j--; )
+    insert_extent_into_skyline (&skyline, extents[j], a, d);
+
+  return skyline;
+}
+
+
+/*
+  minimum distance that can be achieved between baselines. "Clouds" is
+  a skyline pointing down.
+ */
+Real
+skyline_meshing_distance (Array<Skyline_entry> buildings,
+                         Array<Skyline_entry> clouds)
+{
+  int i = buildings.size () -1;
+  int j  = clouds.size() -1;
+
+  Real distance = - infinity_f;
+  
+  while (i > 0 || j > 0)
+    {
+      Interval w = buildings[i].width_;
+      w.intersect(clouds[j].width_);
+      
+      if (!w.empty_b())
+       distance = distance >? (buildings[i].height_ - clouds[j].height_);
+
+      if (i>0 && buildings[i].width_[LEFT] >=  clouds[j].width_[LEFT])
+       {
+         i--;
+       }
+      else if (j > 0 && buildings[i].width_[LEFT] <=  clouds[j].width_[LEFT])
+       {
+         j--;
+       }       
+    }
+
+  return distance;
+}
+
+Skyline_entry::Skyline_entry()
+{
+  height_ = 0.0;
+}
+
+Skyline_entry::Skyline_entry (Interval i, Real r)
+{
+  width_ = i;
+  height_ = r;
+  
+}
index 60c6bd9725400e669c13c04ce94830ba0bf02c4d..4c75541b06319a754c3211dc80486c2ecc640242 100644 (file)
@@ -27,7 +27,7 @@ StaffContext=\translator {
        \consists "Staff_symbol_engraver"
        \consists "Collision_engraver"
        \consists "Rest_collision_engraver"
-       \consists "Accidental_engraver"
+       \consists "New_accidental_engraver"
        \consists "Piano_pedal_engraver"
        \consists "Instrument_name_engraver"
        \consists "Grob_pq_engraver"
index 7bcdb1182fe45b5e1d0005e8709da5c80adbf5fd..9cb4c9dd54f2d24386fe751b03078500da75ff49 100644 (file)
        (font-family . music)
        (meta . ((interfaces . (accidentals-interface staff-symbol-referencer-interface font-interface side-position-interface))))
        ))
+    (Accidental
+     . (
+       (molecule-callback . ,Accidental_interface::brew_molecule)
+       (X-offset-callbacks . (,Side_position_interface::aligned_side))
+;      (after-line-breaking-callback . ,Local_key_item::after_line_breaking)
+       (direction . -1)
+       (left-padding . 0.2)
+       (right-padding . 0.5)
+       (paren-cautionaries . #t)
+       (font-family . music)
+       (meta . ((interfaces . (accidental-interface staff-symbol-referencer-interface font-interface side-position-interface))))
+       ))
+    (AccidentalPlacement
+     . (
+       (X-extent-callback . ,Axis_group_interface::group_extent_callback)
+;      (after-line-breaking-callback . ,Local_key_item::after_line_breaking)
+       (meta . ((interfaces . (accidental-placement-interface))))
+       ))
 
     (Arpeggio
      . (