]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/tuplet-bracket.cc
Fix #580.
[lilypond.git] / lily / tuplet-bracket.cc
index 4d4fbe9acb9b858fff0f76974566ddc862a1a133..41bdec37fc94badd49b8502c30c37b60a3cb0fe3 100644 (file)
@@ -3,7 +3,7 @@
 
   source file of the GNU LilyPond music typesetter
 
 
   source file of the GNU LilyPond music typesetter
 
-  (c) 1997--2006 Jan Nieuwenhuizen <janneke@gnu.org>
+  (c) 1997--2007 Jan Nieuwenhuizen <janneke@gnu.org>
   Han-Wen Nienhuys <hanwen@xs4all.nl>
 */
 
   Han-Wen Nienhuys <hanwen@xs4all.nl>
 */
 
@@ -77,7 +77,6 @@ flatten_number_pair_property (Grob *me,
 /*
   Return beam that encompasses the span of the tuplet bracket.
 */
 /*
   Return beam that encompasses the span of the tuplet bracket.
 */
-
 Grob *
 Tuplet_bracket::parallel_beam (Grob *me_grob, vector<Grob*> const &cols,
                               bool *equally_long)
 Grob *
 Tuplet_bracket::parallel_beam (Grob *me_grob, vector<Grob*> const &cols,
                               bool *equally_long)
@@ -91,8 +90,10 @@ Tuplet_bracket::parallel_beam (Grob *me_grob, vector<Grob*> const &cols,
   Drul_array<Grob*> stems (Note_column::get_stem (cols[0]),
                           Note_column::get_stem (cols.back ()));
 
   Drul_array<Grob*> stems (Note_column::get_stem (cols[0]),
                           Note_column::get_stem (cols.back ()));
 
-  if (dynamic_cast<Item*> (stems[RIGHT])->get_column ()
-      != me->get_bound (RIGHT)->get_column())
+  if (!stems[RIGHT]
+      || !stems[LEFT]
+      || (dynamic_cast<Item*> (stems[RIGHT])->get_column ()
+         != me->get_bound (RIGHT)->get_column ()))
     return 0;
 
   Drul_array<Grob*> beams;
     return 0;
 
   Drul_array<Grob*> beams;
@@ -120,7 +121,7 @@ Tuplet_bracket::parallel_beam (Grob *me_grob, vector<Grob*> const &cols,
 }
 
 
 }
 
 
-MAKE_SCHEME_CALLBACK(Tuplet_bracket,calc_connect_to_neighbors,1);
+MAKE_SCHEME_CALLBACK (Tuplet_bracket, calc_connect_to_neighbors,1);
 SCM
 Tuplet_bracket::calc_connect_to_neighbors (SCM smob)
 {
 SCM
 Tuplet_bracket::calc_connect_to_neighbors (SCM smob)
 {
@@ -135,9 +136,7 @@ Tuplet_bracket::calc_connect_to_neighbors (SCM smob)
   do
     {
       Direction break_dir = bounds[d]->break_status_dir ();
   do
     {
       Direction break_dir = bounds[d]->break_status_dir ();
-      
       Spanner *orig_spanner = dynamic_cast<Spanner*> (me->original ());
       Spanner *orig_spanner = dynamic_cast<Spanner*> (me->original ());
-
       vsize neighbor_idx = me->get_break_index () - break_dir;
       if (break_dir
          && d == RIGHT
       vsize neighbor_idx = me->get_break_index () - break_dir;
       if (break_dir
          && d == RIGHT
@@ -176,7 +175,7 @@ Tuplet_bracket::get_common_x (Spanner *me)
   return commonx;
 }
   
   return commonx;
 }
   
-MAKE_SCHEME_CALLBACK(Tuplet_bracket,calc_control_points,1)
+MAKE_SCHEME_CALLBACK (Tuplet_bracket, calc_control_points,1)
 SCM
 Tuplet_bracket::calc_control_points (SCM smob)
 {
 SCM
 Tuplet_bracket::calc_control_points (SCM smob)
 {
@@ -280,7 +279,6 @@ Tuplet_bracket::print (SCM smob)
     bracket_visibility = ly_scm2bool (bracket);
   else if (bracket == ly_symbol2scm ("if-no-beam"))
     bracket_visibility = !par_beam;
     bracket_visibility = ly_scm2bool (bracket);
   else if (bracket == ly_symbol2scm ("if-no-beam"))
     bracket_visibility = !par_beam;
-
   
   SCM cpoints =  me->get_property ("control-points");
   if (scm_ilength (cpoints) < 2)
   
   SCM cpoints =  me->get_property ("control-points");
   if (scm_ilength (cpoints) < 2)
@@ -296,8 +294,6 @@ Tuplet_bracket::print (SCM smob)
   Interval x_span (points[LEFT][X_AXIS], points[RIGHT][X_AXIS]);
   Drul_array<Real> positions (points[LEFT][Y_AXIS], points[RIGHT][Y_AXIS]);
 
   Interval x_span (points[LEFT][X_AXIS], points[RIGHT][X_AXIS]);
   Drul_array<Real> positions (points[LEFT][Y_AXIS], points[RIGHT][Y_AXIS]);
 
-
-
   Output_def *pap = me->layout ();
 
   Grob *number_grob = unsmob_grob (me->get_object ("tuplet-number"));
   Output_def *pap = me->layout ();
 
   Grob *number_grob = unsmob_grob (me->get_object ("tuplet-number"));
@@ -494,6 +490,7 @@ Tuplet_bracket::calc_position_and_height (Grob *me_grob, Real *offset, Real *dy)
   commony = common_refpoint_of_array (tuplets, commony, Y_AXIS);
   if (Grob *st = Staff_symbol_referencer::get_staff_symbol (me))
     commony = st->common_refpoint (commony, Y_AXIS);
   commony = common_refpoint_of_array (tuplets, commony, Y_AXIS);
   if (Grob *st = Staff_symbol_referencer::get_staff_symbol (me))
     commony = st->common_refpoint (commony, Y_AXIS);
+  Real my_offset = me->relative_coordinate (commony, Y_AXIS);
 
   Grob *commonx = get_common_x (me);
   commonx = common_refpoint_of_array (tuplets, commonx, Y_AXIS);
 
   Grob *commonx = get_common_x (me);
   commonx = common_refpoint_of_array (tuplets, commonx, Y_AXIS);
@@ -504,7 +501,7 @@ Tuplet_bracket::calc_position_and_height (Grob *me_grob, Real *offset, Real *dy)
       Real pad = robust_scm2double (me->get_property ("staff-padding"), -1.0);
       if  (pad >= 0.0)
        {
       Real pad = robust_scm2double (me->get_property ("staff-padding"), -1.0);
       if  (pad >= 0.0)
        {
-         staff = st->extent (commony, Y_AXIS);
+         staff = st->extent (commony, Y_AXIS) - my_offset;
          staff.widen (pad);
        }
     }
          staff.widen (pad);
        }
     }
@@ -514,18 +511,17 @@ Tuplet_bracket::calc_position_and_height (Grob *me_grob, Real *offset, Real *dy)
   bool equally_long = false;
   Grob *par_beam = parallel_beam (me, columns, &equally_long);
   
   bool equally_long = false;
   Grob *par_beam = parallel_beam (me, columns, &equally_long);
   
-
-
   Item *lgr = get_x_bound_item (me, LEFT, dir);
   Item *rgr = get_x_bound_item (me, RIGHT, dir);
   Real x0 = robust_relative_extent (lgr, commonx, X_AXIS)[LEFT];
   Real x1 = robust_relative_extent (rgr, commonx, X_AXIS)[RIGHT];
   Item *lgr = get_x_bound_item (me, LEFT, dir);
   Item *rgr = get_x_bound_item (me, RIGHT, dir);
   Real x0 = robust_relative_extent (lgr, commonx, X_AXIS)[LEFT];
   Real x1 = robust_relative_extent (rgr, commonx, X_AXIS)[RIGHT];
+  bool follow_beam = par_beam
+    && ((get_grob_direction (par_beam) == dir)
+       || to_boolean (par_beam->get_property ("knee")));
 
   vector<Offset> points;
 
   vector<Offset> points;
-
   if (columns.size ()
   if (columns.size ()
-      && par_beam
-      && get_grob_direction (par_beam) == dir 
+      && follow_beam
       && Note_column::get_stem (columns[0])
       && Note_column::get_stem (columns.back ()))
     {
       && Note_column::get_stem (columns[0])
       && Note_column::get_stem (columns.back ()))
     {
@@ -534,16 +530,14 @@ Tuplet_bracket::calc_position_and_height (Grob *me_grob, Real *offset, Real *dy)
        */
       (void) par_beam->get_property ("quantized-positions");
 
        */
       (void) par_beam->get_property ("quantized-positions");
 
-
       Drul_array<Grob *> stems (Note_column::get_stem (columns[0]),
                                Note_column::get_stem (columns.back ()));
 
       Drul_array<Grob *> stems (Note_column::get_stem (columns[0]),
                                Note_column::get_stem (columns.back ()));
 
-      
-      
-
       Real ss = 0.5 * Staff_symbol_referencer::staff_space (me);
       Real ss = 0.5 * Staff_symbol_referencer::staff_space (me);
-      Real lp = ss * robust_scm2double (stems[LEFT]->get_property ("stem-end-position"), 0.0);
-      Real rp = ss * robust_scm2double (stems[RIGHT]->get_property ("stem-end-position"), 0.0);
+      Real lp = ss * robust_scm2double (stems[LEFT]->get_property ("stem-end-position"), 0.0)
+        + stems[LEFT]->get_parent (Y_AXIS)->relative_coordinate (commony, Y_AXIS) - my_offset;
+      Real rp = ss * robust_scm2double (stems[RIGHT]->get_property ("stem-end-position"), 0.0)
+        + stems[RIGHT]->get_parent (Y_AXIS)->relative_coordinate (commony, Y_AXIS) - my_offset;
 
       *dy = rp - lp;
       points.push_back (Offset (stems[LEFT]->relative_coordinate (commonx, X_AXIS) - x0, lp));
 
       *dy = rp - lp;
       points.push_back (Offset (stems[LEFT]->relative_coordinate (commonx, X_AXIS) - x0, lp));
@@ -581,18 +575,17 @@ Tuplet_bracket::calc_position_and_height (Grob *me_grob, Real *offset, Real *dy)
       else
        *dy = 0;
 
       else
        *dy = 0;
 
-      *offset = -dir * infinity_f;      
       for (vsize i = 0; i < columns.size (); i++)
        {
          Interval note_ext = columns[i]->extent (commony, Y_AXIS);
       for (vsize i = 0; i < columns.size (); i++)
        {
          Interval note_ext = columns[i]->extent (commony, Y_AXIS);
-         Real notey = note_ext[dir] - me->relative_coordinate (commony, Y_AXIS);
+         Real notey = note_ext[dir] - my_offset;
 
          Real x = columns[i]->relative_coordinate (commonx, X_AXIS) - x0;
          points.push_back (Offset (x, notey));
        }
     }
 
 
          Real x = columns[i]->relative_coordinate (commonx, X_AXIS) - x0;
          points.push_back (Offset (x, notey));
        }
     }
 
-  if (!(par_beam && get_grob_direction (par_beam) == dir))
+  if (!follow_beam)
     {
       points.push_back (Offset (x0 - x0, staff[dir]));
       points.push_back (Offset (x1 - x0, staff[dir]));
     {
       points.push_back (Offset (x0 - x0, staff[dir]));
       points.push_back (Offset (x1 - x0, staff[dir]));
@@ -636,6 +629,7 @@ Tuplet_bracket::calc_position_and_height (Grob *me_grob, Real *offset, Real *dy)
       while (flip (&d) != LEFT);
     }
 
       while (flip (&d) != LEFT);
     }
 
+  *offset = -dir * infinity_f;
   Real factor = (columns.size () > 1) ? 1 / (x1 - x0) : 1.0;
   for (vsize i = 0; i < points.size (); i++)
     {
   Real factor = (columns.size () > 1) ? 1 / (x1 - x0) : 1.0;
   for (vsize i = 0; i < points.size (); i++)
     {
@@ -654,6 +648,8 @@ Tuplet_bracket::calc_position_and_height (Grob *me_grob, Real *offset, Real *dy)
     Kind of pointless since we put them outside the staff anyway, but
     let's leave code for the future when possibly allow them to move
     into the staff once again.
     Kind of pointless since we put them outside the staff anyway, but
     let's leave code for the future when possibly allow them to move
     into the staff once again.
+  
+    This doesn't seem to support cross-staff tuplets atm.
   */
   if (*dy == 0
       && fabs (*offset) < ss * Staff_symbol_referencer::staff_radius (me))
   */
   if (*dy == 0
       && fabs (*offset) < ss * Staff_symbol_referencer::staff_radius (me))
@@ -737,6 +733,36 @@ Tuplet_bracket::add_tuplet_bracket (Grob *me, Grob *bracket)
   Pointer_group_interface::add_grob (me, ly_symbol2scm ("tuplets"), bracket);
 }
 
   Pointer_group_interface::add_grob (me, ly_symbol2scm ("tuplets"), bracket);
 }
 
+MAKE_SCHEME_CALLBACK (Tuplet_bracket, calc_cross_staff, 1);
+SCM
+Tuplet_bracket::calc_cross_staff (SCM smob)
+{
+  Grob *me = unsmob_grob (smob);
+  Grob *staff_symbol = 0;
+  extract_grob_set (me, "note-columns", cols);
+  bool equally_long = false;
+  Grob *par_beam = parallel_beam (me, cols, &equally_long);
+
+  if (par_beam)
+    return par_beam->get_property ("cross-staff");
+
+  for (vsize i = 0; i < cols.size (); i++)
+    {
+      Grob *stem = unsmob_grob (cols[i]->get_object ("stem"));
+      if (!stem)
+       continue;
+      
+      if (to_boolean (stem->get_property ("cross-staff")))
+       return SCM_BOOL_T;
+
+      Grob *stem_staff = Staff_symbol_referencer::get_staff_symbol (stem);
+      if (staff_symbol && (stem_staff != staff_symbol))
+        return SCM_BOOL_T;
+      staff_symbol = stem_staff;
+    }
+  return SCM_BOOL_F;
+}
+
 ADD_INTERFACE (Tuplet_bracket,
               "A bracket with a number in the middle, used for tuplets. "
               "When the bracket spans  a line break, the value of "
 ADD_INTERFACE (Tuplet_bracket,
               "A bracket with a number in the middle, used for tuplets. "
               "When the bracket spans  a line break, the value of "