From 6e4ac6b25cc04491d1d31445f4b255fea5461f47 Mon Sep 17 00:00:00 2001
From: Joe Neeman <joeneeman@gmail.com>
Date: Sun, 17 Jun 2007 19:22:21 +1000
Subject: [PATCH] introduce Spacing_interface for code sharing between
 Note_spacing and Staff_spacing

---
 lily/include/note-spacing.hh            |   2 -
 lily/include/spacing-interface.hh       |   9 ++
 lily/note-spacing.cc                    |  61 -----------
 lily/spacing-determine-loose-columns.cc |   9 +-
 lily/spacing-interface.cc               | 128 ++++++++++++++++++++++++
 lily/spacing-spanner.cc                 |   4 +-
 lily/staff-spacing.cc                   |   2 -
 lily/system.cc                          |   1 -
 scm/define-grobs.scm                    |   6 +-
 9 files changed, 148 insertions(+), 74 deletions(-)
 create mode 100644 lily/spacing-interface.cc

diff --git a/lily/include/note-spacing.hh b/lily/include/note-spacing.hh
index af04260cea..dcc9b2fe5a 100644
--- a/lily/include/note-spacing.hh
+++ b/lily/include/note-spacing.hh
@@ -20,8 +20,6 @@ public:
   static void get_spacing (Grob *me, Item *, Real, Real, Real *, Real *);
   static void stem_dir_correction (Grob *me, Item *next_col, Real incr,
 				   Real *, Real *);
-  static Item *right_column (Grob *);
-  static Item *left_column (Grob *);
 };
 
 #endif /* NOTE_SPACING_HH */
diff --git a/lily/include/spacing-interface.hh b/lily/include/spacing-interface.hh
index b558ede709..08e404e4e7 100644
--- a/lily/include/spacing-interface.hh
+++ b/lily/include/spacing-interface.hh
@@ -8,8 +8,17 @@
 #include "grob-interface.hh"
 #include "lily-proto.hh"
 
+#ifndef SPACING_INTERFACE_HH
+#define SPACING_INTERFACE_HH
+
 struct Spacing_interface
 {
+  static Real minimum_distance (Grob *me);
+  static Drul_array<Item*> note_columns (Grob *me);
+  static Item* right_column (Grob *me);
+  static Item* left_column (Grob *me);
+
   DECLARE_GROB_INTERFACE();
 };
 
+#endif /* SPACING_INTERFACE_HH */
diff --git a/lily/note-spacing.cc b/lily/note-spacing.cc
index ed18b91913..345b9209e7 100644
--- a/lily/note-spacing.cc
+++ b/lily/note-spacing.cc
@@ -58,12 +58,6 @@ Note_spacing::get_spacing (Grob *me, Item *right_col,
 	  if (d == RIGHT && right_col != it_col)
 	    continue;
 
-	  if (Separation_item::has_interface (it))
-	    {
-	      extents[d].unite (Separation_item::width (it));
-	      continue;
-	    }
-
 	  if (d == LEFT
 	      && Note_column::has_interface (it))
 	    {
@@ -155,61 +149,6 @@ Note_spacing::get_spacing (Grob *me, Item *right_col,
   stem_dir_correction (me, right_col, increment, space, fixed);
 }
 
-Item *
-Note_spacing::left_column (Grob *me)
-{
-  if (!me->is_live ())
-    return 0;
-
-  return dynamic_cast<Item *> (me)->get_column ();
-}
-
-/*
-  Compute the column of the right-items.  This is a big function,
-  since RIGHT-ITEMS may span more columns (eg. if a clef is inserted,
-  this will add a new column to RIGHT-ITEMS. Here we look at the
-  columns, and return the left-most. If there are multiple columns, we
-  prune RIGHT-ITEMS.
-*/
-Item *
-Note_spacing::right_column (Grob *me)
-{
-  if (!me->is_live ())
-    return 0;
-
-  Grob_array *a = unsmob_grob_array (me->get_object ("right-items"));
-  Item *mincol = 0;
-  int min_rank = INT_MAX;
-  bool prune = false;
-  for (vsize i = 0; a && i < a->size (); i++)
-    {
-      Item *ri = a->item (i);
-      Item *col = ri->get_column ();
-
-      int rank = Paper_column::get_rank (col);
-
-      if (rank < min_rank)
-	{
-	  min_rank = rank;
-	  if (mincol)
-	    prune = true;
-
-	  mincol = col;
-	}
-    }
-
-  if (prune && a)
-    {
-      vector<Grob*> &right = a->array_reference ();
-      for (vsize i = right.size (); i--;)
-	{
-	  if (dynamic_cast<Item *> (right[i])->get_column () != mincol)
-	    right.erase (right.begin () + i);
-	}
-    }
-
-  return mincol;
-}
 
 /**
    Correct for optical illusions. See [Wanske] p. 138. The combination
diff --git a/lily/spacing-determine-loose-columns.cc b/lily/spacing-determine-loose-columns.cc
index 45f2f0ae7c..7274ef1363 100644
--- a/lily/spacing-determine-loose-columns.cc
+++ b/lily/spacing-determine-loose-columns.cc
@@ -14,6 +14,7 @@
 #include "paper-column.hh"
 #include "column-x-positions.hh"
 #include "pointer-group-interface.hh"
+#include "spacing-interface.hh"
 #include "spacing-spanner.hh"
 #include "note-spacing.hh"
 #include "moment.hh"
@@ -86,7 +87,7 @@ is_loose_column (Grob *l, Grob *col, Grob *r, Spacing_options const *options)
     return false;
 
   l_neighbor = l_neighbor->get_column ();
-  r_neighbor = dynamic_cast<Item *> (Note_spacing::right_column (r_neighbor));
+  r_neighbor = dynamic_cast<Item *> (Spacing_interface::right_column (r_neighbor));
 
   if (l == l_neighbor && r == r_neighbor)
     return false;
@@ -143,8 +144,8 @@ Spacing_spanner::set_distances_for_loose_col (Grob *me, Grob *c,
       for (vsize k = wishes.size (); k--;)
 	{
 	  Grob *sp = wishes[k];
-	  if (Note_spacing::left_column (sp) != lc
-	      || Note_spacing::right_column (sp) != rc)
+	  if (Spacing_interface::left_column (sp) != lc
+	      || Spacing_interface::right_column (sp) != rc)
 	    continue;
 
 	  if (Note_spacing::has_interface (sp))
@@ -276,7 +277,7 @@ Spacing_spanner::set_explicit_neighbor_columns (vector<Grob*> const &cols)
 	  Item *wish = dynamic_cast<Item *> (wishes[k]);
 
 	  Item *lc = wish->get_column ();
-	  Grob *right = Note_spacing::right_column (wish);
+	  Grob *right = Spacing_interface::right_column (wish);
 
 	  if (!right)
 	    continue;
diff --git a/lily/spacing-interface.cc b/lily/spacing-interface.cc
new file mode 100644
index 0000000000..8a0c353c4b
--- /dev/null
+++ b/lily/spacing-interface.cc
@@ -0,0 +1,128 @@
+/*
+  spacing-interface.cc -- functionality that is shared between Note_spacing
+  and Staff_spacing
+
+  source file of the GNU LilyPond music typesetter
+
+  (c) 2007 Joe Neeman <joeneeman@gmail.com>
+*/
+
+#include "spacing-interface.hh"
+
+#include "grob.hh"
+#include "grob-array.hh"
+#include "item.hh"
+#include "note-column.hh"
+#include "paper-column.hh"
+#include "separation-item.hh"
+#include "skyline.hh"
+
+/* return the minimum distance between the left-items and the right-items of
+   this spacing object */
+Real
+Spacing_interface::minimum_distance (Grob *me)
+{
+  Drul_array<Skyline> skylines = Drul_array<Skyline> (Skyline (RIGHT), Skyline (LEFT));
+  Drul_array<vector<Grob*> > items (ly_scm2link_array (me->get_object ("left-items")),
+				    ly_scm2link_array (me->get_object ("right-items")));
+
+  Direction d = LEFT;
+  do
+    {
+      for (vsize i = 0; i < items[d].size (); i++)
+	if (Separation_item::has_interface (items[d][i]))
+	  {
+	    SCM sky_scm = items[d][i]->get_property ("horizontal-skylines");
+	    Skyline_pair *sky = Skyline_pair::unsmob (sky_scm);
+	    skylines[d].merge ((*sky)[-d]);
+	    
+	    if (d == RIGHT && items[LEFT].size ())
+	      skylines[d].merge (Separation_item::conditional_skyline (items[d][i], items[LEFT][0]));
+	  }
+    }
+  while (flip (&d) != LEFT);
+
+  return skylines[LEFT].distance (skylines[RIGHT]);
+}
+
+/*
+  Compute the column of the right-items.  This is a big function,
+  since RIGHT-ITEMS may span more columns (eg. if a clef is inserted,
+  this will add a new column to RIGHT-ITEMS. Here we look at the
+  columns, and return the left-most. If there are multiple columns, we
+  prune RIGHT-ITEMS.
+*/
+Item *
+Spacing_interface::right_column (Grob *me)
+{
+  if (!me->is_live ())
+    return 0;
+
+  Grob_array *a = unsmob_grob_array (me->get_object ("right-items"));
+  Item *mincol = 0;
+  int min_rank = INT_MAX;
+  bool prune = false;
+  for (vsize i = 0; a && i < a->size (); i++)
+    {
+      Item *ri = a->item (i);
+      Item *col = ri->get_column ();
+
+      int rank = Paper_column::get_rank (col);
+
+      if (rank < min_rank)
+	{
+	  min_rank = rank;
+	  if (mincol)
+	    prune = true;
+
+	  mincol = col;
+	}
+    }
+
+  if (prune && a)
+    {
+      vector<Grob*> &right = a->array_reference ();
+      for (vsize i = right.size (); i--;)
+	{
+	  if (dynamic_cast<Item *> (right[i])->get_column () != mincol)
+	    right.erase (right.begin () + i);
+	}
+    }
+
+  return mincol;
+}
+
+Item *
+Spacing_interface::left_column (Grob *me)
+{
+  if (!me->is_live ())
+    return 0;
+
+  return dynamic_cast<Item *> (me)->get_column ();
+}
+
+Drul_array<Item*>
+Spacing_interface::note_columns (Grob *me)
+{
+  Drul_array<Item*> ret (0, 0);
+  Drul_array<vector<Grob*> > items (ly_scm2link_array (me->get_object ("left-items")),
+				    ly_scm2link_array (me->get_object ("right-items")));
+
+  Direction d = LEFT;
+  do
+    {
+      for (vsize i = 0; i < items[d].size (); i++)
+	if (Note_column::has_interface (items[d][i]))
+	  ret[d] = dynamic_cast<Item*> (items[d][i]);
+    }
+  while (flip (&d) != LEFT);
+
+  return ret;
+}
+
+ADD_INTERFACE (Spacing_interface,
+	       "This object calculates the desired and minimum distances between two columns.",
+
+	       "left-items "
+	       "right-items "
+	       );
diff --git a/lily/spacing-spanner.cc b/lily/spacing-spanner.cc
index 568283846d..721fcd30a4 100644
--- a/lily/spacing-spanner.cc
+++ b/lily/spacing-spanner.cc
@@ -272,8 +272,8 @@ Spacing_spanner::musical_column_spacing (Grob *me,
 	{
 	  Grob *wish = neighbors[i];
 
-	  Item *wish_rcol = Note_spacing::right_column (wish);
-	  if (Note_spacing::left_column (wish) != left_col
+	  Item *wish_rcol = Spacing_interface::right_column (wish);
+	  if (Spacing_interface::left_column (wish) != left_col
 	      || (wish_rcol != right_col && wish_rcol != right_col->original ()))
 	    continue;
 
diff --git a/lily/staff-spacing.cc b/lily/staff-spacing.cc
index b93a4ee6b0..2919602843 100644
--- a/lily/staff-spacing.cc
+++ b/lily/staff-spacing.cc
@@ -269,6 +269,4 @@ ADD_INTERFACE (Staff_spacing,
 
 	       /* properties */
 	       "stem-spacing-correction "
-	       "left-items "
-	       "right-items "
 	       );
diff --git a/lily/system.cc b/lily/system.cc
index eb6d05a881..e8af537be1 100644
--- a/lily/system.cc
+++ b/lily/system.cc
@@ -19,7 +19,6 @@
 #include "paper-score.hh"
 #include "paper-system.hh"
 #include "pointer-group-interface.hh"
-#include "spacing-interface.hh"
 #include "staff-symbol-referencer.hh"
 #include "warn.hh"
 #include "lookup.hh"
diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm
index c3315a3b42..9c8e83d311 100644
--- a/scm/define-grobs.scm
+++ b/scm/define-grobs.scm
@@ -1145,6 +1145,7 @@
 	(Y-extent . ,ly:axis-group-interface::height)
 	(meta . ((class . Item)
 		 (interfaces . (axis-group-interface
+				separation-item-iterface
 				note-column-interface))))))
 
     (NoteHead
@@ -1171,7 +1172,7 @@
 	;; If you ever change this back, please document! --hwn
 	(knee-spacing-correction . 1.0)
 	(meta . ((class . Item)
-		 (interfaces . (
+		 (interfaces . (spacing-interface
 				note-spacing-interface))))))
 
     (NoteName
@@ -1560,7 +1561,8 @@
 	(non-musical . #t)
 	(stem-spacing-correction . 0.4)
 	(meta . ((class . Item)
-		 (interfaces . (staff-spacing-interface))))))
+		 (interfaces . (spacing-interface
+				staff-spacing-interface))))))
 
    
     (StaffSymbol
-- 
2.39.5