]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/spacing-spanner.cc
patch::: 1.3.54.hwn2
[lilypond.git] / lily / spacing-spanner.cc
index df73a595a43266bb6cbc433eb312ca0afc2a4e73..4b413ec6a8cc61d06498e992ef88e0ff93e1dad3 100644 (file)
@@ -3,41 +3,27 @@
   
   source file of the GNU LilyPond music typesetter
   
   
   source file of the GNU LilyPond music typesetter
   
-  (c) 1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  (c) 1999--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
   
  */
 
 #include "spacing-spanner.hh"
   
  */
 
 #include "spacing-spanner.hh"
-#include "score-column.hh"
+#include "paper-column.hh"
 #include "dimensions.hh"
 #include "paper-def.hh"
 #include "warn.hh"
 #include "paper-score.hh"
 #include "line-of-score.hh"
 #include "dimensions.hh"
 #include "paper-def.hh"
 #include "warn.hh"
 #include "paper-score.hh"
 #include "line-of-score.hh"
+#include "misc.hh"
 
 Spacing_spanner::Spacing_spanner ()
 {
 
 Spacing_spanner::Spacing_spanner ()
 {
-  set_elt_property (break_helper_only_scm_sym, SCM_BOOL_T);
-  set_elt_property (transparent_scm_sym, SCM_BOOL_T);
-}
-
-int
-Spacing_spanner::col_count () const
-{
-  return pscore_l_->line_l_->cols_.size ();
-}
-
-Score_column *
-Spacing_spanner::scol (int i)const
-{
-  return dynamic_cast<Score_column*> (pscore_l_->line_l_->cols_[i]);
+  set_extent_callback (0, X_AXIS);
+  set_extent_callback (0, Y_AXIS);  
+  set_elt_property ("transparent", SCM_BOOL_T);
 }
 
 /*
 }
 
 /*
-  cut 'n paste from spring-spacer.cc
-
-  generate springs between columns.
-
 
   The algorithm is partly taken from :
 
 
   The algorithm is partly taken from :
 
@@ -46,34 +32,41 @@ Spacing_spanner::scol (int i)const
   Science, The Ohio State University, 1987.
 
   TOO HAIRY.
   Science, The Ohio State University, 1987.
 
   TOO HAIRY.
+
+  TODO: write comments 
   
  */
 Array<Spring>
   
  */
 Array<Spring>
-Spacing_spanner::do_measure (int col1, int col2) const
+Spacing_spanner::do_measure (Link_array<Paper_column> cols) const
 {
 {
-  for (int i =col1; i < col2; i++)
-    {
-      scol (i)->preprocess ();
-      scol (i)->print ();
-    }
-
   Moment shortest;
   Moment shortest;
+  Moment mean_shortest;
   shortest.set_infinite (1);
   shortest.set_infinite (1);
-  for (int i =col1; i < col2; i++)
+
+  int n = 0;
+  for (int i =0 ; i < cols.size (); i++)  
     {
     {
-      if (scol(i)->musical_b ())
+      if (cols[i]->musical_b ())
        {
        {
-         shortest = shortest <? scol(i)->shortest_starter_mom_;
+         SCM  st = cols[i]->get_elt_property ("shortest-starter-duration");
+         Moment this_shortest = (*SMOB_TO_TYPE(Moment, st));
+         shortest = shortest <? this_shortest;
+         if (!mean_shortest.infty_b ())
+           {
+             n++;
+             mean_shortest += this_shortest;
+           }
        }
     }
        }
     }
+  mean_shortest /= n;
 
   Array<Spring> meas_springs;
 
   Real non_musical_space_strength = paper_l ()->get_var ("breakable_column_space_strength");
 
   Array<Spring> meas_springs;
 
   Real non_musical_space_strength = paper_l ()->get_var ("breakable_column_space_strength");
-  for (int i= col1; i < col2; i++)
+  for (int i= 0; i < cols.size () - 1; i++)
     {
     {
-      Item * l = scol(i);
-      Item * r = scol(i+1);
+      Item * l = cols[i];
+      Item * r = cols[i+1];
       Item * lb = l->find_prebroken_piece (RIGHT);
       Item * rb = r->find_prebroken_piece (LEFT);      
 
       Item * lb = l->find_prebroken_piece (RIGHT);
       Item * rb = r->find_prebroken_piece (LEFT);      
 
@@ -81,8 +74,8 @@ Spacing_spanner::do_measure (int col1, int col2) const
 
       for (int j=0; j < 4; j++)
        {
 
       for (int j=0; j < 4; j++)
        {
-         Score_column * lc = dynamic_cast<Score_column*> (combinations[j][0]);
-         Score_column *rc = dynamic_cast<Score_column*> (combinations[j][1]);
+         Paper_column * lc = dynamic_cast<Paper_column*> (combinations[j][0]);
+         Paper_column *rc = dynamic_cast<Paper_column*> (combinations[j][1]);
          if (!lc || !rc)
            continue;
 
          if (!lc || !rc)
            continue;
 
@@ -90,19 +83,18 @@ Spacing_spanner::do_measure (int col1, int col2) const
          s.item_l_drul_[LEFT] = lc;
          s.item_l_drul_[RIGHT] = rc;
          
          s.item_l_drul_[LEFT] = lc;
          s.item_l_drul_[RIGHT] = rc;
          
-         SCM hint = lc->get_elt_property (extra_space_scm_sym);
-         SCM next_hint = rc->get_elt_property (extra_space_scm_sym);
-         SCM stretch_hint = lc->get_elt_property (stretch_distance_scm_sym);
-         SCM next_stretch_hint = rc->get_elt_property (stretch_distance_scm_sym);        
+         SCM hint = lc->get_elt_property ("extra-space");
+         SCM next_hint = rc->get_elt_property ("extra-space");
+         SCM stretch_hint = lc->get_elt_property ("stretch-distance");
+         SCM next_stretch_hint = rc->get_elt_property ("stretch-distance");      
 
          Real left_distance;
 
          Real left_distance;
-         if (hint != SCM_BOOL_F)
+         if (gh_pair_p (hint))
            {
            {
-             hint = SCM_CDDR (hint);
-             
-             left_distance = gh_scm2double (hint); 
+             left_distance = gh_scm2double (gh_cdr (hint)); 
            }
            }
-         else if (!lc->musical_b() && i+1 < col_count())
+          // 2nd condition should be (i+1 < col_count()), ie. not the last column in score.  FIXME
+         else if (!lc->musical_b() && i+1 < cols.size ()) 
            {
              left_distance= default_bar_spacing (lc,rc,shortest);
            }
            {
              left_distance= default_bar_spacing (lc,rc,shortest);
            }
@@ -127,10 +119,9 @@ Spacing_spanner::do_measure (int col1, int col2) const
 
          
          Real right_dist = 0.0;
 
          
          Real right_dist = 0.0;
-         if (next_hint != SCM_BOOL_F)
+         if (gh_pair_p (next_hint))
            {
            {
-             next_hint = SCM_CADR(next_hint);
-             right_dist += - gh_scm2double (next_hint);
+             right_dist += - gh_scm2double (gh_car (next_hint));
            }
          else
            {
            }
          else
            {
@@ -143,28 +134,32 @@ Spacing_spanner::do_measure (int col1, int col2) const
          */
          if (lc->musical_b () && rc->musical_b ())
            {
          */
          if (lc->musical_b () && rc->musical_b ())
            {
-             if (rc->get_elt_property (contains_grace_scm_sym) == SCM_BOOL_F)
+             if (!to_boolean (rc->get_elt_property ("contains-grace")))
                right_dist *= paper_l ()->get_var ("musical_to_musical_left_spacing_factor");
            }
 
                right_dist *= paper_l ()->get_var ("musical_to_musical_left_spacing_factor");
            }
 
-         if (rc->musical_b () && rc->get_elt_property (contains_grace_scm_sym) != SCM_BOOL_F)
+         if (rc->musical_b () && to_boolean (rc->get_elt_property ("contains-grace")))
            right_dist *= paper_l ()->get_var ("before_grace_spacing_factor");
  
            right_dist *= paper_l ()->get_var ("before_grace_spacing_factor");
  
-         s.distance_f_ = left_distance + right_dist;
+         s.distance_f_ = left_distance + right_dist;
            
          Real stretch_dist = 0.;
            
          Real stretch_dist = 0.;
-         if (stretch_hint != SCM_BOOL_F)
-           stretch_dist += gh_scm2double (SCM_CDDR (stretch_hint));
+         if (gh_number_p (stretch_hint))
+           stretch_dist += gh_scm2double (stretch_hint);
          else
            stretch_dist += left_distance;
          
          else
            stretch_dist += left_distance;
          
-         if (next_stretch_hint != SCM_BOOL_F)
+         if (gh_pair_p (next_stretch_hint))
            // see regtest spacing-tight
            // see regtest spacing-tight
-           stretch_dist += - gh_scm2double (SCM_CADR (next_stretch_hint));
+           stretch_dist += - gh_scm2double (gh_car  (next_stretch_hint));
          else
            stretch_dist += right_dist;
 
          else
            stretch_dist += right_dist;
 
+         if (s.distance_f_ <0)
+           {
+             programming_error("Negative dist, setting to 1.0 PT");
+             s.distance_f_ = 1.0;
+           }
          if (stretch_dist == 0.0)
            {
              /*
          if (stretch_dist == 0.0)
            {
              /*
@@ -186,7 +181,7 @@ Spacing_spanner::do_measure (int col1, int col2) const
    Do something if breakable column has no spacing hints set.
  */
 Real
    Do something if breakable column has no spacing hints set.
  */
 Real
-Spacing_spanner::default_bar_spacing (Score_column *lc, Score_column *rc,
+Spacing_spanner::default_bar_spacing (Paper_column *lc, Paper_column *rc,
                                      Moment shortest) const
 {
   Real symbol_distance = lc->extent (X_AXIS)[RIGHT] ;
                                      Moment shortest) const
 {
   Real symbol_distance = lc->extent (X_AXIS)[RIGHT] ;
@@ -198,33 +193,56 @@ Spacing_spanner::default_bar_spacing (Score_column *lc, Score_column *rc,
   */
   if (delta_t)
     {
   */
   if (delta_t)
     {
-      Real k=  paper_l()->arithmetic_constant (shortest);
-      durational_distance =  paper_l()->length_mom_to_dist (delta_t,k);
+      durational_distance =  get_duration_space (delta_t, shortest);
     }
 
   return  symbol_distance >? durational_distance;
 }
 
 
     }
 
   return  symbol_distance >? durational_distance;
 }
 
 
+/**
+  Get the measure wide constant for arithmetic spacing.
+
+  @see
+  John S. Gourlay. ``Spacing a Line of Music,'' Technical Report
+  OSU-CISRC-10/87-TR35, Department of Computer and Information Science,
+  The Ohio State University, 1987.
+
+  */
+Real
+Spacing_spanner::get_duration_space (Moment d, Moment shortest) const
+{
+  Real log = log_2 (Moment (1,8) <? shortest);
+  Real k=   paper_l ()->get_var ("arithmetic_basicspace")
+    - log;
+  
+  return (log_2 (d) + k) * paper_l ()->get_var ("arithmetic_multiplier");
+}
+
+
 Real
 Real
-Spacing_spanner::note_spacing (Score_column *lc, Score_column *rc, Moment shortest) const
+Spacing_spanner::note_spacing (Paper_column *lc, Paper_column *rc, Moment shortest) const
 {
 {
-  Moment shortest_playing_len = lc->shortest_playing_mom_;
+  Moment shortest_playing_len = 0;
+  SCM s = lc->get_elt_property ("shortest-playing-duration");
+  //  SCM s = lc->get_elt_property ("mean-playing-duration");  
+  if (SMOB_IS_TYPE_B(Moment, s))
+    shortest_playing_len = *SMOB_TO_TYPE (Moment, s);
+
+  
   if (! shortest_playing_len)
     {
   if (! shortest_playing_len)
     {
-      warning (_f ("can't find a ruling note at %s", 
-                  lc->when_mom ().str ()));
+      programming_error ("can't find a ruling note at " + lc->when_mom ().str ());
       shortest_playing_len = 1;
     }
       shortest_playing_len = 1;
     }
+  
   if (! shortest)
     {
   if (! shortest)
     {
-      warning (_f ("no minimum in measure at %s", 
-                  lc->when_mom ().str ()));
+      programming_error ("no minimum in measure at " + lc->when_mom ().str ());
       shortest = 1;
     }
   Moment delta_t = rc->when_mom () - lc->when_mom ();
       shortest = 1;
     }
   Moment delta_t = rc->when_mom () - lc->when_mom ();
-  Real k=  paper_l()->arithmetic_constant(shortest);
-  Real dist = paper_l()->length_mom_to_dist (shortest_playing_len, k);
+  Real dist = get_duration_space (shortest_playing_len, shortest);
   dist *= (double)(delta_t / shortest_playing_len);
 
   dist += stem_dir_correction (lc,rc);
   dist *= (double)(delta_t / shortest_playing_len);
 
   dist += stem_dir_correction (lc,rc);
@@ -240,29 +258,27 @@ Spacing_spanner::note_spacing (Score_column *lc, Score_column *rc, Moment shorte
    This should be more advanced, since relative heights of the note
    heads also influence required correction.
 
    This should be more advanced, since relative heights of the note
    heads also influence required correction.
 
-   Also might not work correctly ico. multi voices or staff changing voices
+   Also might not work correctly in case of multi voices or staff
+   changing voices
 
    TODO: lookup correction distances?  More advanced correction?
    Possibly turn this off?
 
 
    TODO: lookup correction distances?  More advanced correction?
    Possibly turn this off?
 
-   This routine reads the DIR_LIST property of both its L and R arguments.
-*/
+   This routine reads the DIR-LIST property of both its L and R arguments.  */
 Real
 Real
-Spacing_spanner::stem_dir_correction (Score_column*l, Score_column*r) const
+Spacing_spanner::stem_dir_correction (Paper_column*l, Paper_column*r) const
 {
 {
-  SCM dl = l->get_elt_property (dir_list_scm_sym);
-  SCM dr = r->get_elt_property (dir_list_scm_sym);
-  if (dl == SCM_BOOL_F || dr == SCM_BOOL_F)
+  SCM dl = l->get_elt_property ("dir-list");
+  SCM dr = r->get_elt_property ("dir-list");
+  if (dl == SCM_UNDEFINED || dr == SCM_UNDEFINED)
     return 0.0;
 
     return 0.0;
 
-  dl = SCM_CDR (dl);
-  dr = SCM_CDR (dr);
 
   if (scm_ilength (dl) != 1 && scm_ilength (dr) != 1)
     return 0.;
 
 
   if (scm_ilength (dl) != 1 && scm_ilength (dr) != 1)
     return 0.;
 
-  dl = SCM_CAR(dl);
-  dr = SCM_CAR(dr);
+  dl = gh_car (dl);
+  dr = gh_car (dr);
 
   assert (gh_number_p (dl) && gh_number_p(dr));
   int d1 = gh_scm2int (dl);
 
   assert (gh_number_p (dl) && gh_number_p(dr));
   int d1 = gh_scm2int (dl);
@@ -273,7 +289,7 @@ Spacing_spanner::stem_dir_correction (Score_column*l, Score_column*r) const
 
   bool err = false;
   Real correction = 0.0;
 
   bool err = false;
   Real correction = 0.0;
-  Real ssc = paper_l ()->get_realvar(ly_symbol ("stemSpacingCorrection"));
+  Real ssc = paper_l ()->get_var("stemSpacingCorrection");
 
 
   if (d1 && d2)
 
 
   if (d1 && d2)
@@ -299,18 +315,31 @@ Array<Spring>
 Spacing_spanner::get_springs () const
 {
   Array<Spring> springs;
 Spacing_spanner::get_springs () const
 {
   Array<Spring> springs;
-  int last_break =0;
-  for (int i=1; i < col_count (); i++)
+
+  Link_array<Paper_column> all (pscore_l_->line_l_->column_l_arr ()) ;
+
+  int j = 0;
+
+  for (int i = 1; i < all.size (); i++)
     {
     {
-      if (scol (i)->breakable_b ())
+      Paper_column* sc = dynamic_cast<Paper_column*> (all[i]);
+      if (sc->breakable_b ())
         {
         {
-          springs.concat (do_measure (last_break, i));
-          last_break  = i;
+         Link_array<Paper_column> measure (all.slice (j, i+1));          
+          springs.concat (do_measure (measure));
+         j = i;
         }
     }
         }
     }
+
+  /*
+    farewell, cruel world
+   */
+  ((Spacing_spanner*)this)->suicide ();
+  
   return springs;
 }
 
 
 
 
   return springs;
 }
 
 
 
 
+