]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/tuplet-bracket.cc
GDP NR 3.5 MIDI support
[lilypond.git] / lily / tuplet-bracket.cc
index 489d3bc76e58eff0cf199c4b78b31fd398195e98..dde38da22d9fc984a029a6c6b48ca81a5a79207a 100644 (file)
@@ -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;
@@ -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
@@ -280,14 +279,21 @@ 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;
-
   
   
+  /* Don't print a tuplet bracket and number if no control-points were calculated */
   SCM cpoints =  me->get_property ("control-points");
   if (scm_ilength (cpoints) < 2)
     {
       me->suicide ();
       return SCM_EOL;
     }
   SCM cpoints =  me->get_property ("control-points");
   if (scm_ilength (cpoints) < 2)
     {
       me->suicide ();
       return SCM_EOL;
     }
+  /*  if the tuplet does not span any time, i.e. a single-note tuplet, hide
+      the bracket, but still let the number be displayed */
+  if (robust_scm2moment (me->get_bound (LEFT)->get_column ()->get_property ("when"), Moment (0))
+      == robust_scm2moment (me->get_bound (RIGHT)->get_column ()->get_property ("when"), Moment (0)))
+  {
+      bracket_visibility = false;
+  }
   
   Drul_array<Offset> points;
   points[LEFT] = ly_scm2offset (scm_car (cpoints));
   
   Drul_array<Offset> points;
   points[LEFT] = ly_scm2offset (scm_car (cpoints));
@@ -296,8 +302,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,17 +498,23 @@ 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);
 
   Interval staff;
 
   Grob *commonx = get_common_x (me);
   commonx = common_refpoint_of_array (tuplets, commonx, Y_AXIS);
 
   Interval staff;
-  if (Grob *st = Staff_symbol_referencer::get_staff_symbol (me))
+  Grob *st = Staff_symbol_referencer::get_staff_symbol (me);
+
+  /* staff-padding doesn't work correctly on cross-staff tuplets
+     because it only considers one staff symbol. Until this works,
+     disable it. */
+  if (st && !to_boolean (me->get_property ("cross-staff")))
     {
       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 +524,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 +543,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);
+      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);
 
       *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));
@@ -559,10 +566,11 @@ Tuplet_bracket::calc_position_and_height (Grob *me_grob, Real *offset, Real *dy)
       get_bounds (me, &left_col, &right_col);
       if (left_col && right_col)
        {
       get_bounds (me, &left_col, &right_col);
       if (left_col && right_col)
        {
-         Interval rv = right_col->extent (commony, Y_AXIS);
-         Interval lv = left_col->extent (commony, Y_AXIS);
+         Interval rv = Note_column::cross_staff_extent (right_col, commony);
+         Interval lv = Note_column::cross_staff_extent (left_col, commony);
          rv.unite (staff);
          lv.unite (staff);
          rv.unite (staff);
          lv.unite (staff);
+
          Real graphical_dy = rv[dir] - lv[dir];
 
          Slice ls = Note_column::head_positions_interval (left_col);
          Real graphical_dy = rv[dir] - lv[dir];
 
          Slice ls = Note_column::head_positions_interval (left_col);
@@ -581,18 +589,16 @@ 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++)
        {
       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);
-
+         Interval note_ext = Note_column::cross_staff_extent (columns[i], commony);
          Real x = columns[i]->relative_coordinate (commonx, X_AXIS) - x0;
          Real x = columns[i]->relative_coordinate (commonx, X_AXIS) - x0;
-         points.push_back (Offset (x, notey));
+
+         points.push_back (Offset (x, note_ext[dir]));
        }
     }
 
        }
     }
 
-  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,11 +642,12 @@ 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 x = points[i][X_AXIS];
   Real factor = (columns.size () > 1) ? 1 / (x1 - x0) : 1.0;
   for (vsize i = 0; i < points.size (); i++)
     {
       Real x = points[i][X_AXIS];
-      Real tuplety = (*dy) * x * factor;
+      Real tuplety = (*dy) * x * factor + my_offset;
 
       if (points[i][Y_AXIS] * dir > (*offset + tuplety) * dir)
        *offset = points[i][Y_AXIS] - tuplety;
 
       if (points[i][Y_AXIS] * dir > (*offset + tuplety) * dir)
        *offset = points[i][Y_AXIS] - tuplety;
@@ -654,6 +661,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))
@@ -685,16 +694,6 @@ Tuplet_bracket::calc_positions (SCM smob)
 {
   Spanner *me = unsmob_spanner (smob);
 
 {
   Spanner *me = unsmob_spanner (smob);
 
-  /*
-    Don't print if it doesn't span time.
-   */
-  if (robust_scm2moment (me->get_bound (LEFT)->get_column ()->get_property ("when"), Moment (0))
-      == robust_scm2moment (me->get_bound (RIGHT)->get_column ()->get_property ("when"), Moment (0)))
-    {
-      me->suicide ();
-      return SCM_EOL;
-    }
-
   Real dy = 0.0;
   Real offset = 0.0;
   calc_position_and_height (me, &offset, &dy);
   Real dy = 0.0;
   Real offset = 0.0;
   calc_position_and_height (me, &offset, &dy);
@@ -737,14 +736,42 @@ 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);
 }
 
-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 "
-              "@code{break-overshoot} determines how far it extends "
-              "beyond the staff. "
-              "At a line break, the markups in the @code{edge-text} are printed "
-              "at the edges. ",
+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"
+              " @code{break-overshoot} determines how far it extends"
+              " beyond the staff.  At a line break, the markups in the"
+              " @code{edge-text} are printed at the edges.",
 
               /* properties */
               "bracket-flare "
 
               /* properties */
               "bracket-flare "
@@ -763,6 +790,7 @@ ADD_INTERFACE (Tuplet_bracket,
               "shorten-pair "
               "staff-padding "
               "thickness "
               "shorten-pair "
               "staff-padding "
               "thickness "
-              "tuplets ");
+              "tuplets "
+              );