]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/beam.cc
release: 1.3.105
[lilypond.git] / lily / beam.cc
index 1356abe3333460dec86d01cff87cfb3751ad198c..f94c018083f6e3c8617c5649e13a09bca4c45f08 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <math.h> // tanh.
 
-
+#include "molecule.hh" 
 #include "directional-element-interface.hh"
 #include "beaming.hh"
 #include "beam.hh"
 void
 Beam::add_stem (Score_element*me, Score_element*s)
 {
-  Pointer_group_interface gi (me, "stems");
-  gi.add_element (s);
+  Pointer_group_interface:: add_element(me, "stems", s);
   
   s->add_dependency (me);
 
   assert (!Stem::beam_l (s));
-  s->set_elt_property ("beam", me->self_scm_);
+  s->set_elt_property ("beam", me->self_scm ());
 
   add_bound_item (dynamic_cast<Spanner*> (me), dynamic_cast<Item*> (s));
 }
@@ -72,7 +71,7 @@ Beam::get_multiplicity (Score_element*me)
   [Alternatively, stems could set its own directions, according to
    their beam, during 'final-pre-processing'.]
  */
-MAKE_SCHEME_CALLBACK(Beam,before_line_breaking);
+MAKE_SCHEME_CALLBACK(Beam,before_line_breaking,1);
 SCM
 Beam::before_line_breaking (SCM smob)
 {
@@ -84,8 +83,8 @@ Beam::before_line_breaking (SCM smob)
       warning (_ ("beam has less than two stems"));
     }
 
-  if (!Directional_element_interface (me).get ())
-    Directional_element_interface (me).set (get_default_dir (me));
+  if (!Directional_element_interface::get (me))
+    Directional_element_interface::set (me, get_default_dir (me));
 
   auto_knees (me);
   set_stem_directions (me);
@@ -94,9 +93,6 @@ Beam::before_line_breaking (SCM smob)
   return SCM_EOL;
 }
 
-/*
- FIXME
- */
 Direction
 Beam::get_default_dir (Score_element*me) 
 {
@@ -112,7 +108,7 @@ Beam::get_default_dir (Score_element*me)
   for (int i=0; i <stems.size (); i++)
     do { // HUH -- waar slaat dit op?
       Score_element *s = stems[i];
-      Direction sd = Directional_element_interface (s).get ();
+      Direction sd = Directional_element_interface::get (s);
       int current = sd ? (1 + d * sd)/2
        : Stem::get_center_distance (s, (Direction)-d);
 
@@ -124,13 +120,13 @@ Beam::get_default_dir (Score_element*me)
 
     } while (flip(&d) != DOWN);
   
+  SCM func = me->get_elt_property ("dir-function");
+  SCM s = gh_call2 (func,
+                   gh_cons (gh_int2scm (count[UP]),
+                            gh_int2scm (count[DOWN])),
+                   gh_cons (gh_int2scm (total[UP]),
+                            gh_int2scm (total[DOWN])));
 
-  SCM s = scm_eval (gh_list (ly_symbol2scm ("beam-dir-algorithm"),
-                            ly_quote_scm (gh_cons (gh_int2scm (count[UP]),
-                                                   gh_int2scm (count[DOWN]))),
-                            ly_quote_scm (gh_cons (gh_int2scm (total[UP]),
-                                                   gh_int2scm (total[DOWN]))),
-                            SCM_UNDEFINED));
   if (gh_number_p (s) && gh_scm2int (s))
     return to_dir (s);
   
@@ -151,14 +147,14 @@ Beam::set_stem_directions (Score_element*me)
 {
   Link_array<Item> stems
     =Pointer_group_interface__extract_elements (me,  (Item*) 0, "stems");
-  Direction d = Directional_element_interface (me).get ();
+  Direction d = Directional_element_interface::get (me);
   
   for (int i=0; i <stems.size (); i++)
     {
       Score_element *s = stems[i];
       SCM force = s->remove_elt_property ("dir-forced");
       if (!gh_boolean_p (force) || !gh_scm2bool (force))
-       Directional_element_interface (s).set (d);
+       Directional_element_interface ::set (s,d);
     }
 } 
 
@@ -182,8 +178,8 @@ Beam::auto_knee (Score_element*me, String gap_str, bool interstaff_b)
   bool knee_b = false;
   int knee_y = 0;
   SCM gap = me->get_elt_property (gap_str.ch_C());
-  
-  Direction d = Directional_element_interface (me).get ();
+
+  Direction d = Directional_element_interface::get (me);
       Link_array<Item> stems=
        Pointer_group_interface__extract_elements (me, (Item*)0, "stems");
   
@@ -217,7 +213,7 @@ Beam::auto_knee (Score_element*me, String gap_str, bool interstaff_b)
          int y = (int)(Stem::head_positions(s)[d])
            + (int)calc_interstaff_dist (s, dynamic_cast<Spanner*> (me));
 
-         Directional_element_interface (s).set (y < knee_y ? UP : DOWN);
+         Directional_element_interface::set (s,y < knee_y ? UP : DOWN);
          s->set_elt_property ("dir-forced", SCM_BOOL_T);
        }
     }
@@ -243,9 +239,7 @@ Beam::set_stem_shorten (Score_element*m)
 
   int multiplicity = get_multiplicity (me);
 
-  // grace stems?
-  SCM shorten = scm_eval (ly_symbol2scm ("beamed-stem-shorten"));
-
+  SCM shorten = me->get_elt_property ("beamed-stem-shorten");
   if (shorten == SCM_EOL)
     return;
 
@@ -276,7 +270,7 @@ Beam::set_stem_shorten (Score_element*m)
   Set elt properties height and y-position if not set.
   Adjust stem lengths to reach beam.
  */
-MAKE_SCHEME_CALLBACK(Beam,after_line_breaking);
+MAKE_SCHEME_CALLBACK(Beam,after_line_breaking,1);
 SCM
 Beam::after_line_breaking (SCM smob)
 {
@@ -299,8 +293,8 @@ Beam::after_line_breaking (SCM smob)
   /*
     until here, we used only stem_info, which acts as if dir=up
    */
-  y *= Directional_element_interface (me).get ();
-  dy *= Directional_element_interface (me).get ();
+  y *= Directional_element_interface::get (me);
+  dy *= Directional_element_interface::get (me);
 
 
   Real half_space = Staff_symbol_referencer::staff_space (me) / 2;
@@ -342,7 +336,7 @@ Beam::after_line_breaking (SCM smob)
          */
          int quant_dir = 0;
          if (abs (y_shift) > half_space / 2)
-           quant_dir = sign (y_shift) * Directional_element_interface (me).get ();
+           quant_dir = sign (y_shift) * Directional_element_interface::get (me);
          y = quantise_y_f (me, y, dy, quant_dir);
        }
     }
@@ -404,8 +398,8 @@ Beam::suspect_slope_b (Score_element*me, Real y, Real dy)
   */
   Real first_ideal = Stem::calc_stem_info (first_visible_stem (me)).idealy_f_;
   Real last_ideal = Stem::calc_stem_info (last_visible_stem (me)).idealy_f_;
-  Real lengthened = me->paper_l ()->get_var ("beam_lengthened");
-  Real steep = me->paper_l ()->get_var ("beam_steep_slope");
+  Real lengthened = gh_scm2double (me->get_elt_property ("outer-stem-length-limit"));
+  Real steep = gh_scm2double (me->get_elt_property ("slope-limit"));
 
   // ugh -> use commonx
   Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - first_visible_stem (me)->relative_coordinate (0, X_AXIS);
@@ -445,21 +439,23 @@ Beam::calc_slope_damping_f (Score_element*me,Real dy)
 Real
 Beam::calc_stem_y_f (Score_element*me,Item* s, Real y, Real dy) 
 {
-  Real thick = gh_scm2double (me->get_elt_property ("beam-thickness"));
-  thick *= me->paper_l ()->get_var ("staffspace");
-  
   int beam_multiplicity = get_multiplicity (me);
   int stem_multiplicity = (Stem::flag_i (s) - 2) >? 0;
 
-  Real interbeam_f = me->paper_l ()->interbeam_f (beam_multiplicity);
+  SCM space_proc = me->get_elt_property ("space-function");
+  SCM space = gh_call1 (space_proc, gh_int2scm (beam_multiplicity));
+
+  Real thick = gh_scm2double (me->get_elt_property ("thickness")) ;
+  Real interbeam_f = gh_scm2double (space) ;
+
   // ugh -> use commonx
   Real x0 = first_visible_stem (me)->relative_coordinate (0, X_AXIS);
   Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - x0;
   Real stem_y = (dy && dx ? (s->relative_coordinate (0, X_AXIS) - x0) / dx * dy : 0) + y;
 
   /* knee */
-   Direction dir  = Directional_element_interface(me).get ();
-   Direction sdir = Directional_element_interface (s).get ();
+   Direction dir  = Directional_element_interface::get (me);
+   Direction sdir = Directional_element_interface::get (s);
    
     /* knee */
    if (dir!= sdir)
@@ -472,7 +468,7 @@ Beam::calc_stem_y_f (Score_element*me,Item* s, Real y, Real dy)
       // huh, why not for first visible?
        if (Staff_symbol_referencer::staff_symbol_l (s)
           != Staff_symbol_referencer::staff_symbol_l (last_visible_stem (me)))
-        stem_y += Directional_element_interface (me).get ()
+        stem_y += Directional_element_interface::get (me)
           * (beam_multiplicity - stem_multiplicity) * interbeam_f;
       }
 
@@ -484,7 +480,7 @@ Beam::check_stem_length_f (Score_element*me,Real y, Real dy)
 {
   Real shorten = 0;
   Real lengthen = 0;
-  Direction dir = Directional_element_interface (me).get ();
+  Direction dir = Directional_element_interface::get (me);
 
   Link_array<Item> stems=
     Pointer_group_interface__extract_elements (me, (Item*)0, "stems");
@@ -550,7 +546,14 @@ Real
 Beam::quantise_dy_f (Score_element*me,Real dy) 
 {
   Array<Real> a;
-  for (SCM s = scm_eval (ly_symbol2scm ("beam-height-quants")); s !=SCM_EOL; s = gh_cdr (s))
+
+  SCM proc = me->get_elt_property ("height-quants");
+  SCM quants = gh_call2 (proc, me->self_scm (),
+                        gh_double2scm (me->paper_l ()->get_var ("stafflinethickness")
+                                       / 1.0));
+  
+  
+  for (SCM s = quants; gh_pair_p (s); s = gh_cdr (s))
     a.push (gh_scm2double (gh_car (s)));
   
   if (a.size () <= 1)
@@ -580,20 +583,26 @@ Beam::quantise_y_f (Score_element*me,Real y, Real dy, int quant_dir)
   int multiplicity = get_multiplicity (me);
 
   Real staff_space = Staff_symbol_referencer::staff_space (me);
-  SCM quants = scm_eval (gh_list (ly_symbol2scm ("beam-vertical-position-quants"),
-                                 gh_int2scm (multiplicity),
-                                 gh_double2scm (dy/staff_space),
-                                 SCM_UNDEFINED));
+  Real thick = me->paper_l ()->get_var ("stafflinethickness");
+
 
+  SCM proc = me->get_elt_property ("vertical-position-quant-function");
+  SCM quants = scm_apply (proc,
+                         me->self_scm (),
+                         gh_list (gh_int2scm (multiplicity),
+                                  gh_double2scm (dy/staff_space),
+                                  gh_double2scm (thick/staff_space),
+                                  SCM_EOL, SCM_UNDEFINED));
+  
   Array<Real> a;
 
-  for (; quants != SCM_EOL; quants = gh_cdr (quants))
+  for (; gh_pair_p (quants); quants = gh_cdr (quants))
     a.push (gh_scm2double (gh_car (quants)));
 
   if (a.size () <= 1)
     return y;
 
-  Real up_y = Directional_element_interface (me).get () * y;
+  Real up_y = Directional_element_interface::get (me) * y;
   Interval iv = quantise_iv (a, up_y/staff_space) * staff_space;
 
   Real q = up_y - iv[SMALLER] <= iv[BIGGER] - up_y 
@@ -601,7 +610,7 @@ Beam::quantise_y_f (Score_element*me,Real y, Real dy, int quant_dir)
   if (quant_dir)
     q = iv[(Direction)quant_dir];
 
-  return q * Directional_element_interface (me).get ();
+  return q * Directional_element_interface::get (me);
 }
 
 void
@@ -627,8 +636,7 @@ Beam::set_beaming (Score_element*me,Beaming_info_list *beaming)
 /*
   beams to go with one stem.
 
-  BURP
-  clean  me up.
+  FIXME: clean me up.
   */
 Molecule
 Beam::stem_beams (Score_element*me,Item *here, Item *next, Item *prev) 
@@ -641,10 +649,11 @@ Beam::stem_beams (Score_element*me,Item *here, Item *next, Item *prev)
   Real staffline_f = me->paper_l ()->get_var ("stafflinethickness");
   int multiplicity = get_multiplicity (me);
 
+  SCM space_proc = me->get_elt_property ("space-function");
+  SCM space = gh_call1 (space_proc, gh_int2scm (multiplicity));
 
-  Real interbeam_f = me->paper_l ()->interbeam_f (multiplicity);
-  Real thick = gh_scm2double (me->get_elt_property ("beam-thickness"));
-  thick *= me->paper_l ()->get_var ("staffspace");
+  Real thick = gh_scm2double (me->get_elt_property ("thickness")) ;
+  Real interbeam_f = gh_scm2double (space) ;
     
   Real bdy = interbeam_f;
   Real stemdx = staffline_f;
@@ -659,19 +668,19 @@ Beam::stem_beams (Score_element*me,Item *here, Item *next, Item *prev)
   Molecule leftbeams;
   Molecule rightbeams;
 
-  // UGH
   Real nw_f;
   if (!Stem::first_head (here))
     nw_f = 0;
-  else if (Stem::type_i (here)== 1)
-    nw_f = me->paper_l ()->get_var ("wholewidth");
-  else if (Stem::type_i (here) == 2)
-    nw_f = me->paper_l ()->get_var ("notewidth") * 0.8;
-  else
-    nw_f = me->paper_l ()->get_var ("quartwidth");
+  else {
+    int t = Stem::type_i (here); 
+
+    SCM proc = me->get_elt_property ("flag-width-function");
+    SCM result = gh_call1 (proc, gh_int2scm (t));
+    nw_f = gh_scm2double (result);
+  }
 
 
-  Direction dir = Directional_element_interface (me).get ();
+  Direction dir = Directional_element_interface::get (me);
   
   /* half beams extending to the left. */
   if (prev)
@@ -686,7 +695,7 @@ Beam::stem_beams (Score_element*me,Item *here, Item *next, Item *prev)
       w = w/2 <? nw_f;
       Molecule a;
       if (lhalfs)              // generates warnings if not
-       a =  me->lookup_l ()->beam (dydx, w, thick);
+       a =  Lookup::beam (dydx, w, thick);
       a.translate (Offset (-w, -w * dydx));
       for (int j = 0; j  < lhalfs; j++)
        {
@@ -702,12 +711,12 @@ Beam::stem_beams (Score_element*me,Item *here, Item *next, Item *prev)
       int rwholebeams= Stem::beam_count (here,RIGHT) <? Stem::beam_count (next,LEFT) ;
 
       Real w = next->relative_coordinate (0, X_AXIS) - here->relative_coordinate (0, X_AXIS);
-      Molecule a = me->lookup_l ()->beam (dydx, w + stemdx, thick);
+      Molecule a = Lookup::beam (dydx, w + stemdx, thick);
       a.translate_axis( - stemdx/2, X_AXIS);
       int j = 0;
       Real gap_f = 0;
 
-      SCM gap = me->get_elt_property ("beam-gap");
+      SCM gap = me->get_elt_property ("gap");
       if (gh_number_p (gap))
        {
          int gap_i = gh_scm2int ( (gap));
@@ -722,7 +731,7 @@ Beam::stem_beams (Score_element*me,Item *here, Item *next, Item *prev)
          // TODO: notehead widths differ for different types
          gap_f = nw_f / 2;
          w -= 2 * gap_f;
-         a = me->lookup_l ()->beam (dydx, w + stemdx, thick);
+         a = Lookup::beam (dydx, w + stemdx, thick);
        }
 
       for (; j  < rwholebeams; j++)
@@ -734,7 +743,7 @@ Beam::stem_beams (Score_element*me,Item *here, Item *next, Item *prev)
 
       w = w/2 <? nw_f;
       if (rhalfs)
-       a = me->lookup_l ()->beam (dydx, w, thick);
+       a = Lookup::beam (dydx, w, thick);
 
       for (; j  < rwholebeams + rhalfs; j++)
        {
@@ -753,7 +762,7 @@ Beam::stem_beams (Score_element*me,Item *here, Item *next, Item *prev)
   return leftbeams;
 }
 
-MAKE_SCHEME_CALLBACK(Beam,brew_molecule);
+MAKE_SCHEME_CALLBACK(Beam,brew_molecule,1);
 SCM
 Beam::brew_molecule (SCM smob)
 {
@@ -797,7 +806,7 @@ Beam::brew_molecule (SCM smob)
   mol.translate_axis (x0 
     - dynamic_cast<Spanner*> (me)->get_bound (LEFT)->relative_coordinate (0, X_AXIS), X_AXIS);
 
-  return mol.create_scheme ();
+  return mol.smobbed_copy ();
 }
 
 int
@@ -877,18 +886,22 @@ Beam::last_visible_stem(Score_element*me)
     
     rest -> stem -> beam -> interpolate_y_position ()
 */
-Real
-Beam::rest_collision_callback (Score_element *rest, Axis a )
+MAKE_SCHEME_CALLBACK(Beam,rest_collision_callback,2);
+SCM
+Beam::rest_collision_callback (SCM element_smob, SCM axis)
 {
+  Score_element *rest = unsmob_element (element_smob);
+  Axis a = (Axis) gh_scm2int (axis);
+  
   assert (a == Y_AXIS);
 
   Score_element * st = unsmob_element (rest->get_elt_property ("stem"));
   Score_element * stem = st;
   if (!stem)
-    return 0.0;
+    return gh_double2scm (0.0);
   Score_element * beam = unsmob_element (stem->get_elt_property ("beam"));
   if (!beam || !Beam::has_interface (beam) || !Beam::visible_stem_count (beam))
-    return 0.0;
+    return gh_double2scm (0.0);
 
   // make callback for rest from this.
   Real beam_dy = 0;
@@ -913,7 +926,9 @@ Beam::rest_collision_callback (Score_element *rest, Axis a )
   Real beamy = (stem->relative_coordinate (0, X_AXIS) - x0) * dydx + beam_y;
 
   Real staff_space =   Staff_symbol_referencer::staff_space (rest);
-  Real rest_dim = rest->extent (Y_AXIS)[d]*2.0 / staff_space ;
+
+  
+  Real rest_dim = rest->extent (rest, Y_AXIS)[d]*2.0 / staff_space ; // refp??
 
   Real minimum_dist
     = gh_scm2double (rest->get_elt_property ("minimum-beam-collision-distance"));
@@ -929,7 +944,7 @@ Beam::rest_collision_callback (Score_element *rest, Axis a )
   if (discrete_dist < stafflines+1)
     discrete_dist = int (ceil (discrete_dist / 2.0)* 2.0);
 
-  return  (-d *  discrete_dist);
+  return gh_double2scm  (-d *  discrete_dist);
 }
 
 
@@ -942,9 +957,6 @@ Beam::has_interface (Score_element*me)
 void
 Beam::set_interface (Score_element*me)
 {
-  Pointer_group_interface g (me, "stems");
-  g.set_interface ();
-
   /*
     why the init? No way to tell difference between default and user
     override.  */