]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/tie-formatting-problem.cc
Web-ja: update introduction
[lilypond.git] / lily / tie-formatting-problem.cc
index 3e76c120b1a0468cc15df15637202c80e098b5d9..905718469cf0b7e696366219b37c6cee5acf4169 100644 (file)
@@ -1,7 +1,7 @@
 /*
   This file is part of LilyPond, the GNU music typesetter.
 
-  Copyright (C) 2005--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
+  Copyright (C) 2005--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
 
 
   LilyPond is free software: you can redistribute it and/or modify
@@ -29,6 +29,7 @@
 #include "misc.hh"
 #include "note-head.hh"
 #include "rhythmic-head.hh"
+#include "semi-tie.hh"
 #include "spanner.hh"
 #include "staff-symbol-referencer.hh"
 #include "stem.hh"
@@ -56,8 +57,8 @@ Interval
 Tie_formatting_problem::get_attachment (Real y, Drul_array<int> columns) const
 {
   Interval attachments (0, 0);
-  Direction d = LEFT;
-  do
+
+  for (LEFT_and_RIGHT (d))
     {
       Tuple2<int> key (columns[d], int (d));
       Chord_outline_map::const_iterator i (chord_outlines_.find (key));
@@ -66,7 +67,6 @@ Tie_formatting_problem::get_attachment (Real y, Drul_array<int> columns) const
       else
         attachments[d] = i->second.height (y);
     }
-  while (flip (&d) != LEFT);
 
   return attachments;
 }
@@ -99,11 +99,11 @@ Tie_formatting_problem::set_column_chord_outline (vector<Item *> bounds,
   for (vsize i = 0; i < bounds.size (); i++)
     {
       Grob *head = bounds[i];
-      if (!Note_head::has_interface (head))
+      if (!has_interface<Note_head> (head))
         continue;
 
       if (!stem)
-        stem = unsmob_grob (head->get_object ("stem"));
+        stem = unsmob<Grob> (head->get_object ("stem"));
 
       Real p = Staff_symbol_referencer::get_position (head);
       Interval y ((p - 1) * 0.5 * staff_space,
@@ -149,9 +149,10 @@ Tie_formatting_problem::set_column_chord_outline (vector<Item *> bounds,
           else
             {
               if (use_horizontal_spacing_ || !Stem::get_beam (stem))
-                stem_end_position = Stem::stem_end_position (stem) * staff_space * .5;
+                stem_end_position = stem->extent (stem, Y_AXIS)[get_grob_direction (stem)];
               else
-                stem_end_position = Stem::note_head_positions (stem)[get_grob_direction (stem)]
+                // May want to change this to the stem's pure height...
+                stem_end_position = Stem::head_positions (stem)[get_grob_direction (stem)]
                                     * staff_space * .5;
             }
 
@@ -170,9 +171,13 @@ Tie_formatting_problem::set_column_chord_outline (vector<Item *> bounds,
 
           if (dir == LEFT)
             {
-              Box flag_box = Stem::get_translated_flag (stem).extent_box ();
-              flag_box.translate ( Offset (x[RIGHT], X_AXIS));
-              boxes.push_back (flag_box);
+              Grob *flag = Stem::flag (stem);
+              if (flag)
+                {
+                  Grob *commony = stem->common_refpoint (flag, Y_AXIS);
+                  boxes.push_back (Box (flag->extent (x_refpoint_, X_AXIS),
+                                        flag->extent (commony, Y_AXIS)));
+                }
             }
         }
       else
@@ -207,9 +212,9 @@ Tie_formatting_problem::set_column_chord_outline (vector<Item *> bounds,
               boxes.push_back (Box (x, y));
             }
 
-          Grob *acc = unsmob_grob (heads[i]->get_object ("accidental-grob"));
+          Grob *acc = unsmob<Grob> (heads[i]->get_object ("accidental-grob"));
           if (acc)
-            acc->get_property ("stencil"); /* trigger tie-related suicide */
+            acc->get_property ("after-line-breaking"); /* trigger tie-related suicide */
 
           if (acc && acc->is_live () && dir == RIGHT)
             {
@@ -222,8 +227,7 @@ Tie_formatting_problem::set_column_chord_outline (vector<Item *> bounds,
 
     }
 
-  Direction updowndir = DOWN;
-  do
+  for (DOWN_and_UP (updowndir))
     {
       Interval x;
       Interval y;
@@ -239,10 +243,8 @@ Tie_formatting_problem::set_column_chord_outline (vector<Item *> bounds,
       if (!x.is_empty ())
         boxes.push_back (Box (x, y));
     }
-  while (flip (&updowndir) != DOWN);
 
-  /* todo: the horizon_padding is somewhat arbitrary */
-  chord_outlines_[key] = Skyline (boxes, details_.skyline_padding_, Y_AXIS, -dir);
+  chord_outlines_[key] = Skyline (boxes, Y_AXIS, -dir).padded (details_.skyline_padding_);
   if (bounds[0]->break_status_dir ())
     {
       Interval iv (Axis_group_interface::staff_extent (bounds[0], x_refpoint_, X_AXIS, y_refpoint_, Y_AXIS));
@@ -335,14 +337,14 @@ Tie_formatting_problem::from_ties (vector<Grob *> const &ties)
 
   details_.from_grob (ties[0]);
 
-  Direction d = LEFT;
-  do
+  for (LEFT_and_RIGHT (d))
     {
       vector<Item *> bounds;
 
       for (vsize i = 0; i < ties.size (); i++)
         {
-          Item *it = dynamic_cast<Spanner *> (ties[i])->get_bound (d);
+          Spanner *tie = dynamic_cast<Spanner *> (ties[i]);
+          Item *it = tie->get_bound (d);
           if (it->break_status_dir ())
             it = it->get_column ();
 
@@ -351,19 +353,18 @@ Tie_formatting_problem::from_ties (vector<Grob *> const &ties)
 
       set_chord_outline (bounds, d);
     }
-  while (flip (&d) != LEFT);
 
   for (vsize i = 0; i < ties.size (); i++)
     {
+      Spanner *tie = dynamic_cast<Spanner *> (ties[i]);
       Tie_specification spec;
-      spec.from_grob (ties[i]);
+      spec.from_grob (tie);
 
-      do
+      for (LEFT_and_RIGHT (d))
         {
-          spec.note_head_drul_[d] = Tie::head (ties[i], d);
-          spec.column_ranks_[d] = Tie::get_column_rank (ties[i], d);
+          spec.note_head_drul_[d] = Tie::head (tie, d);
+          spec.column_ranks_[d] = Tie::get_column_rank (tie, d);
         }
-      while (flip (&d) != LEFT);
       specifications_.push_back (spec);
     }
 }
@@ -381,8 +382,9 @@ Tie_formatting_problem::from_semi_ties (vector<Grob *> const &semi_ties, Directi
   int column_rank = -1;
   for (vsize i = 0; i < semi_ties.size (); i++)
     {
+      Item *semi_tie = dynamic_cast<Item *> (semi_ties[i]);
       Tie_specification spec;
-      Item *head = unsmob_item (semi_ties[i]->get_object ("note-head"));
+      Item *head = Semi_tie::head (semi_tie);
 
       if (!head)
         programming_error ("LV tie without head?!");
@@ -392,10 +394,10 @@ Tie_formatting_problem::from_semi_ties (vector<Grob *> const &semi_ties, Directi
           spec.position_ = int (Staff_symbol_referencer::get_position (head));
         }
 
-      spec.from_grob (semi_ties[i]);
+      spec.from_grob (semi_tie);
 
       spec.note_head_drul_[head_dir] = head;
-      column_rank = Tie::get_column_rank (semi_ties[i], head_dir);
+      column_rank = Semi_tie::get_column_rank (semi_tie);
       spec.column_ranks_ = Drul_array<int> (column_rank, column_rank);
       heads.push_back (head);
       specifications_.push_back (spec);
@@ -438,7 +440,8 @@ Tie_configuration *
 Tie_formatting_problem::get_configuration (int pos, Direction dir, Drul_array<int> columns,
                                            bool tune_dy) const
 {
-  int key_components[] =
+  int key_components[]
+  =
   {
     pos, dir, columns[LEFT], columns[RIGHT]
   };
@@ -497,22 +500,25 @@ Tie_formatting_problem::generate_configuration (int pos, Direction dir,
         size.
 
        */
+      Interval staff_span
+        = Staff_symbol_referencer::staff_span (details_.staff_symbol_referencer_);
+      staff_span.widen (-1);
+      bool const within_staff = staff_span.contains (pos);
       if (head_positions_slice (columns[LEFT]).contains (pos)
           || head_positions_slice (columns[RIGHT]).contains (pos)
-          || abs (pos) < 2 * Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_))
+          || within_staff)
         {
           if (h < details_.intra_space_threshold_ * 0.5 * details_.staff_space_)
             {
-              if (!Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos)
-                  && abs (pos) < 2 * Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_))
-                {
-                  conf->center_tie_vertically (details_);
-                }
-              else if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos))
+              if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos))
                 {
                   conf->delta_y_ += dir *
                                     details_.tip_staff_line_clearance_ * 0.5 * details_.staff_space_;
                 }
+              else if (within_staff)
+                {
+                  conf->center_tie_vertically (details_);
+                }
             }
           else
             {
@@ -559,8 +565,7 @@ Tie_formatting_problem::generate_configuration (int pos, Direction dir,
         It would be better to check D against HEAD-DIRECTION if
         applicable.
       */
-      Direction d = LEFT;
-      do
+      for (LEFT_and_RIGHT (d))
         {
           Real y = conf->position_ * details_.staff_space_ * 0.5 + conf->delta_y_;
           if (get_stem_extent (conf->column_ranks_[d], d, X_AXIS).is_empty ()
@@ -571,7 +576,6 @@ Tie_formatting_problem::generate_configuration (int pos, Direction dir,
             = d * min (d * conf->attachment_x_[d],
                        d * (get_stem_extent (conf->column_ranks_[d], d, X_AXIS)[-d] - d * details_.stem_gap_));
         }
-      while (flip (&d) != LEFT);
     }
   return conf;
 }
@@ -625,8 +629,7 @@ Tie_formatting_problem::score_aptitude (Tie_configuration *conf,
       penalty += p;
   }
 
-  Direction d = LEFT;
-  do
+  for (LEFT_and_RIGHT (d))
     {
       if (!spec.note_head_drul_[d])
         continue;
@@ -646,24 +649,21 @@ Tie_formatting_problem::score_aptitude (Tie_configuration *conf,
         penalty += p;
 
     }
-  while (flip (&d) != LEFT);
 
   if (ties_conf
       && ties_conf->size () == 1)
     {
-      Direction d = LEFT;
       Drul_array<Grob *> stems (0, 0);
-      do
+      for (LEFT_and_RIGHT (d))
         {
           if (!spec.note_head_drul_[d])
             continue;
 
-          Grob *stem = unsmob_grob (spec.note_head_drul_[d]->get_object ("stem"));
+          Grob *stem = unsmob<Grob> (spec.note_head_drul_[d]->get_object ("stem"));
           if (stem
               && Stem::is_normal_stem (stem))
             stems[d] = stem;
         }
-      while (flip (&d) != LEFT);
 
       bool tie_stem_dir_ok = true;
       bool tie_position_dir_ok = true;
@@ -724,9 +724,11 @@ Tie_formatting_problem::score_configuration (Tie_configuration *conf) const
   Real top_y = tip_y + conf->dir_ * height;
   Real top_pos = 2 * top_y / details_.staff_space_;
   Real round_top_pos = rint (top_pos);
+  Interval staff_span
+    = Staff_symbol_referencer::staff_span (details_.staff_symbol_referencer_);
   if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_,
                                         int (round_top_pos))
-      && Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_) > top_y)
+      && staff_span[UP] * 0.5 > top_y)
     {
       conf->add_score (details_.staff_line_collision_penalty_
                        * peak_around (0.1 * details_.center_staff_line_clearance_,
@@ -736,10 +738,11 @@ Tie_formatting_problem::score_configuration (Tie_configuration *conf) const
     }
 
   int rounded_tip_pos = int (rint (tip_pos));
+  staff_span.widen (-1);
   if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, rounded_tip_pos)
       && (head_positions_slice (conf->column_ranks_[LEFT]).contains (rounded_tip_pos)
           || head_positions_slice (conf->column_ranks_[RIGHT]).contains (rounded_tip_pos)
-          || abs (rounded_tip_pos) < 2 * Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_))
+          || staff_span.contains (rounded_tip_pos))
      )
     {
       conf->add_score (details_.staff_line_collision_penalty_
@@ -1032,11 +1035,10 @@ vector<Tie_configuration_variation>
 Tie_formatting_problem::generate_extremal_tie_variations (Ties_configuration const &ties) const
 {
   vector<Tie_configuration_variation> vars;
-  Direction d = DOWN;
   for (int i = 1; i <= details_.multi_tie_region_size_; i++)
     {
       Drul_array<Tie_configuration *> configs (0, 0);
-      do
+      for (DOWN_and_UP (d))
         {
           const Tie_configuration &config = boundary (ties, d, 0);
           if (config.dir_ == d
@@ -1051,7 +1053,6 @@ Tie_formatting_problem::generate_extremal_tie_variations (Ties_configuration con
               vars.push_back (var);
             }
         }
-      while (flip (&d) != DOWN);
       if (configs[LEFT] && configs[RIGHT])
         {
           Tie_configuration_variation var;
@@ -1074,8 +1075,7 @@ Tie_formatting_problem::generate_single_tie_variations (Ties_configuration const
     sz = 1;
   for (int i = 0; i < sz; i++)
     {
-      Direction d = LEFT;
-      do
+      for (LEFT_and_RIGHT (d))
         {
           if (i == 0
               && ties[0].dir_ == d)
@@ -1094,7 +1094,6 @@ Tie_formatting_problem::generate_single_tie_variations (Ties_configuration const
               vars.push_back (var);
             }
         }
-      while (flip (&d) != LEFT);
     }
   return vars;
 }
@@ -1205,7 +1204,8 @@ Tie_formatting_problem::set_manual_tie_configuration (SCM manual_configs)
             {
               spec.has_manual_position_ = true;
               spec.manual_position_ = scm_to_double (scm_car (entry));
-              spec.has_manual_delta_y_ = (scm_inexact_p (scm_car (entry)) == SCM_BOOL_T);
+              /* TODO: check whether inexact? is an appropriate condition here */
+              spec.has_manual_delta_y_ = (scm_is_true (scm_inexact_p (scm_car (entry))));
             }
 
           if (scm_is_number (scm_cdr (entry)))