]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/new-fingering-engraver.cc
Run grand-replace (issue 3765)
[lilypond.git] / lily / new-fingering-engraver.cc
index 2749d5cb3f623d1c46fd050c2f5b03bf7c9ab784..51eb26c6d29a1f89aa20836950cba09dc1f36e22 100644 (file)
@@ -1,27 +1,36 @@
 /*
-  fingering-engraver.cc -- implement New_fingering_engraver
+  This file is part of LilyPond, the GNU music typesetter.
 
-  source file of the GNU LilyPond music typesetter
+  Copyright (C) 1998--2014 Han-Wen Nienhuys <hanwen@xs4all.nl>
 
-  (c) 1998--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
+  LilyPond is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LilyPond is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "engraver.hh"
 
 #include "international.hh"
+#include "item.hh"
 #include "rhythmic-head.hh"
 #include "script-interface.hh"
 #include "self-alignment-interface.hh"
 #include "side-position-interface.hh"
 #include "stem.hh"
 #include "stream-event.hh"
-#include "item.hh"
 #include "warn.hh"
 
 #include "translator.icc"
 
-
-
 struct Finger_tuple
 {
   Grob *head_;
@@ -41,7 +50,7 @@ struct Finger_tuple
 };
 
 bool
-operator< (Finger_tuple const &a, Finger_tuple const &b)
+operator < (Finger_tuple const &a, Finger_tuple const &b)
 {
   return a.position_ < b.position_;
 }
@@ -53,7 +62,8 @@ class New_fingering_engraver : public Engraver
   vector<Finger_tuple> articulations_;
   vector<Finger_tuple> string_numbers_;
 
-  vector<Grob*> heads_;
+  vector<Grob *> heads_;
+  vector<Grob *> accidentals_;
   Grob *stem_;
 
   void position_all ();
@@ -62,15 +72,22 @@ public:
 protected:
   void stop_translation_timestep ();
   DECLARE_ACKNOWLEDGER (rhythmic_head);
+  DECLARE_ACKNOWLEDGER (inline_accidental);
   DECLARE_ACKNOWLEDGER (stem);
   void add_fingering (Grob *, SCM,
-                     vector<Finger_tuple> *,
-                     Stream_event *, Stream_event *);
+                      vector<Finger_tuple> *,
+                      Stream_event *, Stream_event *);
   void add_script (Grob *, Stream_event *, Stream_event *);
   void add_string (Grob *, Stream_event *, Stream_event *);
   void position_scripts (SCM orientations, vector<Finger_tuple> *);
 };
 
+void
+New_fingering_engraver::acknowledge_inline_accidental (Grob_info inf)
+{
+  accidentals_.push_back (inf.grob ());
+}
+
 void
 New_fingering_engraver::acknowledge_rhythmic_head (Grob_info inf)
 {
@@ -85,32 +102,40 @@ New_fingering_engraver::acknowledge_rhythmic_head (Grob_info inf)
       Stream_event *ev = unsmob_stream_event (scm_car (s));
 
       if (!ev)
-       continue;
+        continue;
 
       if (ev->in_event_class ("fingering-event"))
-       add_fingering (inf.grob (),
-                      ly_symbol2scm ("Fingering"),
-                      &fingerings_,
-                      ev, note_ev);
+        add_fingering (inf.grob (),
+                       ly_symbol2scm ("Fingering"),
+                       &fingerings_,
+                       ev, note_ev);
       else if (ev->in_event_class ("text-script-event"))
-       ev->origin ()->warning (_ ("cannot add text scripts to individual note heads"));
+        ev->origin ()->warning (_ ("cannot add text scripts to individual note heads"));
       else if (ev->in_event_class ("script-event"))
-       add_script (inf.grob (), ev, note_ev);
+        add_script (inf.grob (), ev, note_ev);
       else if (ev->in_event_class ("string-number-event"))
-       add_fingering (inf.grob (),
-                      ly_symbol2scm ("StringNumber"), &string_numbers_,
-                      ev, note_ev);
+        {
+          // String numbers are used in calculating harmonics even
+          // when we don't want them displayed.  So don't make space
+          // for them if 'stencil is #f
+          Grob *g = make_item ("StringNumber", ev->self_scm ());
+          if (g->get_property ("stencil") != SCM_BOOL_F)
+            add_fingering (inf.grob (),
+                           ly_symbol2scm ("StringNumber"), &string_numbers_,
+                           ev, note_ev);
+          g->suicide (); // Kill grob created to check stencil
+        }
       else if (ev->in_event_class ("stroke-finger-event"))
-       add_fingering (inf.grob (),
-                      ly_symbol2scm ("StrokeFinger"), &stroke_fingerings_,
-                      ev, note_ev);
+        add_fingering (inf.grob (),
+                       ly_symbol2scm ("StrokeFinger"), &stroke_fingerings_,
+                       ev, note_ev);
       else if (ev->in_event_class ("harmonic-event"))
-       {
-         inf.grob ()->set_property ("style", ly_symbol2scm ("harmonic"));
-         Grob *d = unsmob_grob (inf.grob ()->get_object ("dot"));
-         if (d && !to_boolean (get_property ("harmonicDots")))
-           d->suicide ();
-       }
+        {
+          inf.grob ()->set_property ("style", ly_symbol2scm ("harmonic"));
+          Grob *d = unsmob_grob (inf.grob ()->get_object ("dot"));
+          if (d && !to_boolean (get_property ("harmonicDots")))
+            d->suicide ();
+        }
     }
 
   heads_.push_back (inf.grob ());
@@ -124,35 +149,36 @@ New_fingering_engraver::acknowledge_stem (Grob_info inf)
 
 void
 New_fingering_engraver::add_script (Grob *head,
-                                   Stream_event *event,
-                                   Stream_event *note)
+                                    Stream_event *event,
+                                    Stream_event * /* note */)
 {
-  (void) note;
-
   Finger_tuple ft;
 
   Grob *g = make_item ("Script", event->self_scm ());
   make_script_from_event (g, context (),
-                         event->get_property ("articulation-type"), 0);
+                          event->get_property ("articulation-type"), 0);
   ft.script_ = g;
   ft.script_->set_parent (head, X_AXIS);
-  
+
+  SCM forced_dir = event->get_property ("direction");
+  if (to_dir (forced_dir))
+    ft.script_->set_property ("direction", forced_dir);
+
   articulations_.push_back (ft);
 }
 
 void
 New_fingering_engraver::add_fingering (Grob *head,
-                                      SCM grob_sym,
-                                      vector<Finger_tuple> *tuple_vector,
-                                      Stream_event *event,
-                                      Stream_event *hevent)
+                                       SCM grob_sym,
+                                       vector<Finger_tuple> *tuple_vector,
+                                       Stream_event *event,
+                                       Stream_event *hevent)
 {
   Finger_tuple ft;
 
   ft.script_ = internal_make_item (grob_sym, event->self_scm (),
-                                  ly_symbol2string (grob_sym).c_str (),
-                                  __FILE__, __LINE__, __FUNCTION__
-                                  );
+                                   ly_symbol2string (grob_sym).c_str (),
+                                   __FILE__, __LINE__, __FUNCTION__);
 
   Side_position_interface::add_support (ft.script_, head);
 
@@ -165,11 +191,15 @@ New_fingering_engraver::add_fingering (Grob *head,
 
 void
 New_fingering_engraver::position_scripts (SCM orientations,
-                                         vector<Finger_tuple> *scripts)
+                                          vector<Finger_tuple> *scripts)
 {
   for (vsize i = 0; i < scripts->size (); i++)
-    if (stem_ && to_boolean (scripts->at (i).script_->get_property ("add-stem-support")))
-      Side_position_interface::add_support (scripts->at (i).script_, stem_);
+    if (stem_)
+      {
+        Side_position_interface::add_support (scripts->at (i).script_, stem_);
+        if (Grob *flag = unsmob_grob (stem_->get_object ("flag")))
+          Side_position_interface::add_support (scripts->at (i).script_, flag);
+      }
 
   /*
     This is not extremely elegant, but we have to do a little
@@ -192,10 +222,10 @@ New_fingering_engraver::position_scripts (SCM orientations,
     {
       SCM d = (*scripts)[i].finger_event_->get_property ("direction");
       if (to_dir (d))
-       {
-         ((to_dir (d) == UP) ? up : down).push_back ((*scripts)[i]);
-         scripts->erase (scripts->begin () + i);
-       }
+        {
+          ((to_dir (d) == UP) ? up : down).push_back ((*scripts)[i]);
+          scripts->erase (scripts->begin () + i);
+        }
     }
 
   vector_sort (*scripts, less<Finger_tuple> ());
@@ -208,16 +238,16 @@ New_fingering_engraver::position_scripts (SCM orientations,
   if (left_p || right_p)
     {
       if (up_p && !up.size () && scripts->size ())
-       {
-         up.push_back (scripts->back ());
-         scripts->pop_back ();
-       }
+        {
+          up.push_back (scripts->back ());
+          scripts->pop_back ();
+        }
 
       if (down_p && !down.size () && scripts->size ())
-       {
-         down.push_back ((*scripts)[0]);
-         scripts->erase (scripts->begin ());
-       }
+        {
+          down.push_back ((*scripts)[0]);
+          scripts->erase (scripts->begin ());
+        }
 
       horiz.insert (horiz.end (), scripts->begin (), scripts->end ());
     }
@@ -235,10 +265,10 @@ New_fingering_engraver::position_scripts (SCM orientations,
   else
     {
       if (!down_p)
-       {
-         warning (_ ("no placement found for fingerings"));
-         warning (_ ("placing below"));
-       }
+        {
+          warning (_ ("no placement found for fingerings"));
+          warning (_ ("placing below"));
+        }
       down.insert (down.end (), scripts->begin (), scripts->end ());
       scripts->clear ();
     }
@@ -249,12 +279,15 @@ New_fingering_engraver::position_scripts (SCM orientations,
       Grob *f = ft.script_;
       f->set_parent (ft.head_, X_AXIS);
       f->set_parent (ft.head_, Y_AXIS);
-      f->set_property ("avoid-slur", SCM_BOOL_F);
+      f->set_property ("avoid-slur", ly_symbol2scm ("inside"));
       if (hordir == LEFT
-         && unsmob_grob (ft.head_->get_object ("accidental-grob")))
-       Side_position_interface::add_support (f,
-                                             unsmob_grob (ft.head_->get_object ("accidental-grob")));
-                                             
+          && unsmob_grob (ft.head_->get_object ("accidental-grob")))
+        Side_position_interface::add_support (f,
+                                              unsmob_grob (ft.head_->get_object ("accidental-grob")));
+      else if (unsmob_grob (ft.head_->get_object ("dot")))
+        Side_position_interface::add_support (f,
+                                              unsmob_grob (ft.head_->get_object ("dot")));
+
       Self_alignment_interface::set_align_self (f, Y_AXIS);
       Self_alignment_interface::set_center_parent (f, Y_AXIS);
       Side_position_interface::set_axis (f, X_AXIS);
@@ -262,28 +295,25 @@ New_fingering_engraver::position_scripts (SCM orientations,
       f->set_property ("direction", scm_from_int (hordir));
     }
 
-  int finger_prio = 200;
-
-  Direction d = DOWN;
   Drul_array< vector<Finger_tuple> > vertical (down, up);
-  do
+  for (DOWN_and_UP (d))
     {
       for (vsize i = 0; i < vertical[d].size (); i++)
-       {
-         Finger_tuple ft = vertical[d][i];
-         Grob *f = ft.script_;
-         f->set_parent (ft.head_, X_AXIS);
-         f->set_property ("script-priority",
-                          scm_from_int (finger_prio + d * ft.position_));
-
-         Self_alignment_interface::set_align_self (f, X_AXIS);
-         Self_alignment_interface::set_center_parent (f, X_AXIS);
-         Side_position_interface::set_axis (f, Y_AXIS);
-      
-         f->set_property ("direction", scm_from_int (d));
-       }
+        {
+          Finger_tuple ft = vertical[d][i];
+          Grob *f = ft.script_;
+          int finger_prio = robust_scm2int (f->get_property ("script-priority"), 200);
+          f->set_parent (ft.head_, X_AXIS);
+          f->set_property ("script-priority",
+                           scm_from_int (finger_prio + d * ft.position_));
+
+          Self_alignment_interface::set_align_self (f, X_AXIS);
+          Self_alignment_interface::set_center_parent (f, X_AXIS);
+          Side_position_interface::set_axis (f, Y_AXIS);
+
+          f->set_property ("direction", scm_from_int (d));
+        }
     }
-  while (flip (&d) != DOWN);
 }
 
 void
@@ -294,43 +324,46 @@ New_fingering_engraver::stop_translation_timestep ()
   heads_.clear ();
 }
 
-
 void
 New_fingering_engraver::position_all ()
 {
   if (fingerings_.size ())
     {
       position_scripts (get_property ("fingeringOrientations"),
-                       &fingerings_);
+                        &fingerings_);
       fingerings_.clear ();
     }
 
   if (string_numbers_.size ())
     {
       position_scripts (get_property ("stringNumberOrientations"),
-                       &string_numbers_);
+                        &string_numbers_);
       string_numbers_.clear ();
     }
 
   if (stroke_fingerings_.size ())
     {
       position_scripts (get_property ("strokeFingerOrientations"),
-                       &stroke_fingerings_);
+                        &stroke_fingerings_);
       stroke_fingerings_.clear ();
     }
-  
+
   for (vsize i = articulations_.size (); i--;)
     {
       Grob *script = articulations_[i].script_;
 
+      for (vsize j = 0; j < accidentals_.size (); j++)
+        Side_position_interface::add_support (script, accidentals_[j]);
+
+      accidentals_.resize (0);
       for (vsize j = heads_.size (); j--;)
-       Side_position_interface::add_support (script, heads_[j]);
+        Side_position_interface::add_support (script, heads_[j]);
 
       if (stem_ && to_dir (script->get_property ("side-relative-direction")))
-       script->set_object ("direction-source", stem_->self_scm ());
+        script->set_object ("direction-source", stem_->self_scm ());
 
       if (stem_ && to_boolean (script->get_property ("add-stem-support")))
-       Side_position_interface::add_support (script, stem_);
+        Side_position_interface::add_support (script, stem_);
     }
   articulations_.clear ();
 }
@@ -340,28 +373,28 @@ New_fingering_engraver::New_fingering_engraver ()
   stem_ = 0;
 }
 
-
 ADD_ACKNOWLEDGER (New_fingering_engraver, rhythmic_head);
+ADD_ACKNOWLEDGER (New_fingering_engraver, inline_accidental);
 ADD_ACKNOWLEDGER (New_fingering_engraver, stem);
 
 ADD_TRANSLATOR (New_fingering_engraver,
-               /* doc */
-               "Create fingering scripts for notes in a new chord.  This"
-               " engraver is ill-named, since it also takes care of"
-               " articulations and harmonic note heads.",
-
-               /* create */
-               "Fingering "
-               "StringNumber "
-               "StrokeFinger "
-               "Script ",
-
-               /* read */
-               "fingeringOrientations "
-               "harmonicDots "
-               "strokeFingerOrientations "
-               "stringNumberOrientations ",
-               
-               /* write */
-               ""
-               );
+                /* doc */
+                "Create fingering scripts for notes in a new chord.  This"
+                " engraver is ill-named, since it also takes care of"
+                " articulations and harmonic note heads.",
+
+                /* create */
+                "Fingering "
+                "StringNumber "
+                "StrokeFinger "
+                "Script ",
+
+                /* read */
+                "fingeringOrientations "
+                "harmonicDots "
+                "strokeFingerOrientations "
+                "stringNumberOrientations ",
+
+                /* write */
+                ""
+               );