]> git.donarmstrong.com Git - lilypond.git/commitdiff
Uses exact horizontal skylines for accidental placement.
authorMike Solomon <mike@apollinemike.com>
Fri, 14 Sep 2012 05:20:22 +0000 (07:20 +0200)
committerMike Solomon <mike@apollinemike.com>
Fri, 14 Sep 2012 05:20:22 +0000 (07:20 +0200)
Removes approximations hardcoded in accidental.cc.
Adds right-padding to accidentals' left spines to avoid too-close placement.

lily/accidental-placement.cc
lily/accidental.cc
lily/include/accidental-interface.hh
lily/include/skyline-pair.hh
lily/include/skyline.hh
lily/side-position-interface.cc
lily/skyline-pair.cc
lily/skyline.cc
scm/define-grobs.scm

index 5b6cfb735b7d956fb934f9934bd7305802ec3ff6..169fe39fdd15d3804e6e036874928b7d1ad0a785 100644 (file)
@@ -27,6 +27,7 @@
 #include "pointer-group-interface.hh"
 #include "rhythmic-head.hh"
 #include "skyline.hh"
+#include "skyline-pair.hh"
 #include "stream-event.hh"
 #include "warn.hh"
 
@@ -115,16 +116,14 @@ Accidental_placement::get_relevant_accidentals (vector<Grob *> const &elts, Grob
 
 struct Accidental_placement_entry
 {
-  Skyline left_skyline_;
-  Skyline right_skyline_;
-  Interval vertical_extent_;
-  vector<Box> extents_;
+  Skyline_pair horizontal_skylines_;
   vector<Grob *> grobs_;
 };
 
 Real ape_priority (Accidental_placement_entry const *a)
 {
-  return a->vertical_extent_[UP];
+  // right is up because we're horizontal
+  return a->horizontal_skylines_.right ();
 }
 
 bool ape_less (Accidental_placement_entry *const &a,
@@ -261,17 +260,17 @@ set_ape_skylines (Accidental_placement_entry *ape,
           offset -= a->extent (a, X_AXIS).length () + padding;
         }
 
-      vector<Box> boxes = Accidental_interface::accurate_boxes (a, common);
-      ape->extents_.insert (ape->extents_.end (), boxes.begin (), boxes.end ());
-
-      for (vsize j = boxes.size (); j--;)
-        ape->vertical_extent_.unite (boxes[j][Y_AXIS]);
+      if (Skyline_pair *sky = Skyline_pair::unsmob (a->get_property ("horizontal-skylines")))
+        {
+          Skyline_pair copy (*sky);
+          copy.raise (a->relative_coordinate (common[X_AXIS], X_AXIS));
+          copy.shift (a->relative_coordinate (common[Y_AXIS], Y_AXIS));
+          ape->horizontal_skylines_.merge (copy);
+        }
 
       last_octave = p->get_octave ();
       last_alteration = p->get_alteration ();
     }
-  ape->left_skyline_ = Skyline (ape->extents_, Y_AXIS, LEFT);
-  ape->right_skyline_ = Skyline (ape->extents_, Y_AXIS, RIGHT);
 }
 
 static vector<Grob *>
@@ -375,13 +374,13 @@ position_apes (Grob *me,
     {
       Accidental_placement_entry *ape = apes[i];
 
-      Real offset = -ape->right_skyline_.distance (left_skyline);
+      Real offset = -ape->horizontal_skylines_[RIGHT].distance (left_skyline);
       if (isinf (offset))
         offset = last_offset;
       else
         offset -= padding;
 
-      Skyline new_left_skyline = ape->left_skyline_;
+      Skyline new_left_skyline = ape->horizontal_skylines_[LEFT];
       new_left_skyline.raise (offset);
       new_left_skyline.merge (left_skyline);
       left_skyline = new_left_skyline;
@@ -390,8 +389,12 @@ position_apes (Grob *me,
       for (vsize j = ape->grobs_.size (); j--;)
         ape->grobs_[j]->translate_axis (offset, X_AXIS);
 
-      for (vsize j = ape->extents_.size (); j--;)
-        width.unite (offset + ape->extents_[j][X_AXIS]);
+      for (LEFT_and_RIGHT (d))
+        {
+          Real mh = ape->horizontal_skylines_[d].max_height ();
+          if (!isinf (mh))
+            width.add_point (mh);
+        }
 
       last_offset = offset;
     }
index 3cc399f84d30f03d2fee4b25d51d617bc06ff317..0cf270f52aa60124a31fdb836fda1704fb71ec53 100644 (file)
@@ -25,6 +25,7 @@
 #include "paper-column.hh"
 #include "pitch.hh"
 #include "stencil.hh"
+#include "skyline-pair.hh"
 
 Stencil
 parenthesize (Grob *me, Stencil m)
@@ -68,6 +69,53 @@ Accidental_interface::width (SCM smob)
   return get_extent (unsmob_grob (smob), X_AXIS);
 }
 
+MAKE_SCHEME_CALLBACK (Accidental_interface, horizontal_skylines, 1);
+SCM
+Accidental_interface::horizontal_skylines (SCM smob)
+{
+  Grob *me = unsmob_grob (smob);
+  if (!me->is_live ())
+    return Skyline_pair ().smobbed_copy ();
+
+  /*
+   * Using the print function may trigger a suicide
+   * before line breaking. It is therefore `unpure' (c).
+   * We use the more basic get_stencil.
+   */
+  Stencil *my_stencil = unsmob_stencil (get_stencil (me));
+  Skyline_pair *sky =
+    Skyline_pair::unsmob
+      (Stencil::skylines_from_stencil
+        (my_stencil->smobbed_copy (), 0.0, Y_AXIS));
+
+  if (!sky)
+    return Skyline_pair ().smobbed_copy ();
+
+  SCM alist = me->get_property ("glyph-name-alist");
+  SCM alt = me->get_property ("alteration");
+  string glyph_name = robust_scm2string (ly_assoc_get (alt, alist, SCM_BOOL_F),
+                                                       "");
+  if (glyph_name == "accidentals.flat"
+      || glyph_name == "accidentals.flatflat")
+    {
+      // a bit more padding for the right of the stem
+      // we raise the stem horizontally to a bit less than the average
+      // horizontal "height" of the entire glyph. This will bring flats
+      // closer to doubleflats, which looks better (MS opinion).
+      // this should work for all fonts where the flat is not
+      // completely bizarre
+      Real left = my_stencil->extent (X_AXIS)[LEFT];
+      Real right = my_stencil->extent (X_AXIS)[RIGHT] * 0.375;
+      Real down = my_stencil->extent (Y_AXIS)[DOWN];
+      Real up = my_stencil->extent (Y_AXIS)[UP];
+      vector<Box> boxes;
+      boxes.push_back (Box (Interval (left, right), Interval (down, up)));
+      Skyline merge_with_me (boxes, Y_AXIS, RIGHT);
+      (*sky)[RIGHT].merge (merge_with_me);
+    }
+  return sky->smobbed_copy ();
+}
+
 MAKE_SCHEME_CALLBACK (Accidental_interface, pure_height, 3);
 SCM
 Accidental_interface::pure_height (SCM smob, SCM start_scm, SCM)
@@ -89,85 +137,6 @@ Accidental_interface::pure_height (SCM smob, SCM start_scm, SCM)
   return ly_interval2scm (Interval ());
 }
 
-vector<Box>
-Accidental_interface::accurate_boxes (Grob *me, Grob **common)
-{
-  Box b;
-  b[X_AXIS] = me->extent (me, X_AXIS);
-  b[Y_AXIS] = me->extent (me, Y_AXIS);
-
-  vector<Box> boxes;
-
-  bool parens = to_boolean (me->get_property ("parenthesized"));
-  if (!me->is_live ())
-    return boxes;
-
-  if (!to_boolean (me->get_property ("restore-first"))
-      && !parens)
-    {
-      SCM alist = me->get_property ("glyph-name-alist");
-      SCM alt = me->get_property ("alteration");
-      string glyph_name = robust_scm2string (ly_assoc_get (alt, alist, SCM_BOOL_F),
-                                             "");
-
-      if (glyph_name == "accidentals.flat"
-          || glyph_name == "accidentals.mirroredflat")
-        {
-          Box stem = b;
-          Box bulb = b;
-
-          /*
-            we could make the stem thinner, but that places the flats
-            really close.
-          */
-          Direction bulb_dir
-            = glyph_name == "accidentals.mirroredflat" ? LEFT : RIGHT;
-          stem[X_AXIS][bulb_dir] = stem[X_AXIS].center ();
-
-          /*
-            To prevent vertical alignment for 6ths
-          */
-          stem[Y_AXIS] *= 1.1;
-          bulb[Y_AXIS][UP] *= .35;
-
-          boxes.push_back (bulb);
-          boxes.push_back (stem);
-        }
-      else if (glyph_name == "accidentals.natural")
-        {
-          Box lstem = b;
-          Box rstem = b;
-          Box belly = b;
-
-          lstem[Y_AXIS] *= 1.1;
-          rstem[Y_AXIS] *= 1.1;
-
-          belly[Y_AXIS] *= 0.75;
-          lstem[X_AXIS][RIGHT] *= .33;
-          rstem[X_AXIS][LEFT] = rstem[X_AXIS].linear_combination (1.0 / 3.0);
-          lstem[Y_AXIS][DOWN] = belly[Y_AXIS][DOWN];
-          rstem[Y_AXIS][UP] = belly[Y_AXIS][UP];
-          boxes.push_back (belly);
-          boxes.push_back (lstem);
-          boxes.push_back (rstem);
-        }
-      /*
-        TODO: add support for, double flat.
-      */
-    }
-
-  if (!boxes.size ())
-    boxes.push_back (b);
-
-  Offset o (me->relative_coordinate (common[X_AXIS], X_AXIS),
-            me->relative_coordinate (common[Y_AXIS], Y_AXIS));
-
-  for (vsize i = boxes.size (); i--;)
-    boxes[i].translate (o);
-
-  return boxes;
-}
-
 MAKE_SCHEME_CALLBACK (Accidental_interface, print, 1);
 SCM
 Accidental_interface::print (SCM smob)
index bf4bfb7a58b51adef7e586ad95810c2fceee9d3a..9c9b97b580e432086e7d1eb79b6f9b7afbcdd482 100644 (file)
@@ -32,11 +32,11 @@ public:
   DECLARE_SCHEME_CALLBACK (print, (SCM));
   DECLARE_SCHEME_CALLBACK (height, (SCM));
   DECLARE_SCHEME_CALLBACK (width, (SCM));
+  DECLARE_SCHEME_CALLBACK (horizontal_skylines, (SCM));
   DECLARE_SCHEME_CALLBACK (pure_height, (SCM, SCM, SCM));
 
   DECLARE_GROB_INTERFACE ();
   static string get_fontcharname (string style, int alteration);
-  static vector<Box> accurate_boxes (Grob *me, Grob **common);
   static SCM get_stencil (Grob *me);
 };
 
index 1d02674814c7d9247249634ec0dc624eba31630e..566b9be3f74c74d94e8619500b77bb8815e07468 100644 (file)
@@ -35,6 +35,8 @@ public:
   Skyline_pair (vector<Skyline_pair> const &skypairs);
   Skyline_pair (Box const &, Axis a);
 
+  Real left () const;
+  Real right () const;
   void raise (Real);
   void shift (Real);
   void deholify ();
index 0cb9fdcc81f5f23474f28c0ac2fbd16b713180aa..c300895fee11bed4e109a896bb3989529b2b59c1 100644 (file)
@@ -90,6 +90,8 @@ public:
   Real height (Real airplane) const;
   Real max_height () const;
   Real max_height_position () const;
+  Real left () const;
+  Real right () const;
   void set_minimum_height (Real height);
   void clear ();
   bool is_empty () const;
index 5a0d16606c9faa6eecbd406b98641e061156f9b7..b515aa3d5277835828b339b8252ed88e3c829de9 100644 (file)
@@ -259,39 +259,31 @@ Side_position_interface::skyline_side_position (Grob *me, Axis a,
 
       if (e)
         {
-          if (Accidental_interface::has_interface (e))
-            {
-              vector<Box> bs = Accidental_interface::accurate_boxes (e, common);
-              boxes.insert (boxes.end (), bs.begin (), bs.end ());
-            }
-          else
-            {
-              if (Note_column::has_interface (e->get_parent (X_AXIS))
-                  && to_boolean (me->get_property ("add-stem-support")))
-                {
-                  note_column_map[e->get_parent (X_AXIS)].push_back (e);
-                  continue;
-                }
-
-              Skyline_pair *sp = Skyline_pair::unsmob (e->get_property ("vertical-skylines"));
-              if (sp && a == Y_AXIS && !pure)
-                {
-                  Skyline_pair copy = Skyline_pair (*sp);
-                  copy.shift (e->relative_coordinate (common[X_AXIS], X_AXIS));
-                  copy.raise (e->relative_coordinate (common[Y_AXIS], Y_AXIS));
-                  skyps.push_back (copy);
-                  continue;
-                }
-              Box b;
-              for (Axis ax = X_AXIS; ax < NO_AXES; incr (ax))
-                b[ax] = e->maybe_pure_extent (common[ax], ax, pure, start, end);
-
-              if (b[X_AXIS].is_empty () || b[Y_AXIS].is_empty ())
-                continue;
-
-              boxes.push_back (b);
-              min_h = minmax (dir, b[a][-dir], min_h);
-            }
+           if (Note_column::has_interface (e->get_parent (X_AXIS))
+               && to_boolean (me->get_property ("add-stem-support")))
+             {
+               note_column_map[e->get_parent (X_AXIS)].push_back (e);
+               continue;
+             }
+
+           Skyline_pair *sp = Skyline_pair::unsmob (e->get_property ("vertical-skylines"));
+           if (sp && a == Y_AXIS && !pure)
+             {
+               Skyline_pair copy = Skyline_pair (*sp);
+               copy.shift (e->relative_coordinate (common[X_AXIS], X_AXIS));
+               copy.raise (e->relative_coordinate (common[Y_AXIS], Y_AXIS));
+               skyps.push_back (copy);
+               continue;
+             }
+           Box b;
+           for (Axis ax = X_AXIS; ax < NO_AXES; incr (ax))
+             b[ax] = e->maybe_pure_extent (common[ax], ax, pure, start, end);
+
+           if (b[X_AXIS].is_empty () || b[Y_AXIS].is_empty ())
+             continue;
+
+           boxes.push_back (b);
+           min_h = minmax (dir, b[a][-dir], min_h);
         }
     }
 
index bbfe9234fcd9dbdc44eb3e33de244d3a61f85771..164117c35bdb62b59516eafe08a8d725e1456fe0 100644 (file)
@@ -90,6 +90,18 @@ Skyline_pair::print () const
   skylines_[DOWN].print ();
 }
 
+Real
+Skyline_pair::left () const
+{
+  return min (skylines_[UP].left (), skylines_[DOWN].left ());
+}
+
+Real
+Skyline_pair::right () const
+{
+  return max (skylines_[UP].right (), skylines_[DOWN].right ());
+}
+
 void
 Skyline_pair::print_points () const
 {
index 3501d311acc7a2fe88ff05f687f83a769dd502e0..1d6e4d5e78e81c2efb24b88a54ddae297035e4fa 100644 (file)
@@ -766,6 +766,28 @@ Skyline::max_height () const
   return sky_ * ret;
 }
 
+Real
+Skyline::left () const
+{
+  for (list<Building>::const_iterator i (buildings_.begin ());
+       i != buildings_.end (); i++)
+    if (i->y_intercept_ > -infinity_f)
+      return i->start_;
+
+  return infinity_f;
+}
+
+Real
+Skyline::right () const
+{
+  for (list<Building>::const_reverse_iterator i (buildings_.rbegin ());
+       i != buildings_.rend (); ++i)
+    if (i->y_intercept_ > -infinity_f)
+      return i->end_;
+
+  return -infinity_f;
+}
+
 Real
 Skyline::max_height_position () const
 {
index cc8a73556567a3c556ffc568abbc233599ab0dd8..cc83a365a8415c57619f8c3c6686dc2fc1272f72 100644 (file)
@@ -33,6 +33,7 @@
        (glyph-name . ,accidental-interface::glyph-name)
        (glyph-name-alist . ,standard-alteration-glyph-name-alist)
        (stencil . ,ly:accidental-interface::print)
+       (horizontal-skylines . ,ly:accidental-interface::horizontal-skylines)
        (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
        (X-extent . ,ly:accidental-interface::width)
        (Y-extent . ,ly:accidental-interface::height)