]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 1320: Scheme bar line interface (part 1/2: recoding)
authorMarc Hohl <marc@hohlart.de>
Wed, 20 Jun 2012 07:14:29 +0000 (09:14 +0200)
committerMarc Hohl <marc@hohlart.de>
Wed, 1 Aug 2012 05:41:44 +0000 (07:41 +0200)
23 files changed:
lily/auto-beam-engraver.cc
lily/bar-engraver.cc
lily/bar-line.cc
lily/clef-engraver.cc
lily/cue-clef-engraver.cc
lily/custos-engraver.cc
lily/grob-scheme.cc
lily/hairpin.cc
lily/include/bar-line.hh
lily/include/span-bar.hh [deleted file]
lily/key-engraver.cc
lily/mark-engraver.cc
lily/span-bar-engraver.cc
lily/span-bar-stub-engraver.cc
lily/span-bar.cc [deleted file]
lily/staff-spacing.cc
lily/vertical-align-engraver.cc
lily/volta-engraver.cc
scm/bar-line.scm [new file with mode: 0644]
scm/define-grob-interfaces.scm
scm/lily-library.scm
scm/lily.scm
scm/output-lib.scm

index 87ab20e52460b21614265289ec4395335f567830..fe9c94ae542ea1bf502f7272eb25aa06c97c01af 100644 (file)
@@ -17,7 +17,6 @@
   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "bar-line.hh"
 #include "beaming-pattern.hh"
 #include "beam.hh"
 #include "context.hh"
index 63f5e83384e794a756af375d9cff863120872722..b2594a2cb871a8f4b5cff207083e36b18245aaf3 100644 (file)
@@ -18,7 +18,6 @@
   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "bar-line.hh"
 #include "context.hh"
 #include "score-engraver.hh"
 #include "warn.hh"
index 0cd0339235b41c307459670210ea35c27f69d66d..fe4406956c2e9b5a531a8d71f86a3f083c80c536 100644 (file)
 */
 
 #include "bar-line.hh"
-
-#include "all-font-metrics.hh"
-#include "font-interface.hh"
-#include "line-interface.hh"
-#include "lookup.hh"
-#include "output-def.hh"
 #include "paper-column.hh"
-#include "staff-symbol-referencer.hh"
-
-MAKE_SCHEME_CALLBACK (Bar_line, calc_bar_extent, 1)
-SCM
-Bar_line::calc_bar_extent (SCM smob)
-{
-  Interval result;
-  Grob *me = unsmob_grob (smob);
-  if (Grob *staff = Staff_symbol_referencer::get_staff_symbol (me))
-    {
-      result = staff->extent (staff, Y_AXIS);
-
-      /* Due to rounding problems, bar lines extending to the outermost edges
-         of the staff lines appear wrongly in on-screen display
-         (and, to a lesser extent, in print) - they stick out a pixel.
-         The solution is to extend bar lines only to the middle
-         of the staff line - unless they have different colors,
-         when it would be undesirable.
-      */
-      SCM bar_line_color = me->get_property ("color");
-      SCM staff_color = staff->get_property ("color");
-      Real radius = Staff_symbol_referencer::staff_radius (me);
-      if (bar_line_color == staff_color && radius)
-        result *= (1 - 0.5 * (Staff_symbol_referencer::line_thickness (me) / radius));
-    }
-  return ly_interval2scm (result);
-}
-
-Interval
-Bar_line::bar_y_extent (Grob *me, Grob *refpoint)
-{
-  Interval iv = robust_scm2interval (me->get_property ("bar-extent"), Interval ());
-
-  iv.translate (me->relative_coordinate (refpoint, Y_AXIS));
-  return iv;
-}
 
 bool
 Bar_line::non_empty_barline (Grob *me)
 {
-  return has_interface (me) && !me->extent (me, X_AXIS).is_empty ();
-}
-
-MAKE_SCHEME_CALLBACK (Bar_line, print, 1);
-SCM
-Bar_line::print (SCM smob)
-{
-  Grob *me = unsmob_grob (smob);
-
-  SCM s = me->get_property ("glyph-name");
-  SCM extent = me->get_property ("bar-extent");
-
-  if (scm_is_string (s) && is_number_pair (extent))
-    {
-      string str = ly_scm2string (s);
-      Interval ex = ly_scm2interval (extent);
-      if (ex.length () > 0)
-        {
-          Stencil result = compound_barline (me, str, ex, false);
-
-          return result.smobbed_copy ();
-        }
-    }
-  return SCM_EOL;
+  return me->internal_has_interface (ly_symbol2scm ("bar-line-interface"))
+         && !me->extent (me, X_AXIS).is_empty ();
 }
-
-Stencil
-Bar_line::compound_barline (Grob *me, string str, Interval const &extent,
-                            bool rounded)
-{
-  Real kern = robust_scm2double (me->get_property ("kern"), 1);
-  Real thinkern = robust_scm2double (me->get_property ("thin-kern"), 1);
-  Real hair = robust_scm2double (me->get_property ("hair-thickness"), 1);
-  Real fatline = robust_scm2double (me->get_property ("thick-thickness"), 1);
-
-  Real staffline = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness"));
-  Real staff_space = Staff_symbol_referencer::staff_space (me);
-
-  kern *= staffline;
-  thinkern *= staffline;
-  hair *= staffline;
-  fatline *= staffline;
-
-  Stencil thin = simple_barline (me, hair, extent, rounded);
-  Stencil thick = simple_barline (me, fatline, extent, rounded);
-  Stencil dot = Font_interface::get_default_font (me)->find_by_name ("dots.dot");
-
-  int lines = Staff_symbol_referencer::line_count (me);
-  Real dist
-    = ((lines & 1 || lines == 0)
-       ? 1
-       : (staff_space < 2 ? 2 : .5)) * staff_space;
-  Stencil colon (dot);
-  colon.translate_axis (dist, Y_AXIS);
-  colon.add_stencil (dot);
-  colon.translate_axis (-dist / 2, Y_AXIS);
-
-  Real const h = extent.length ();
-  Stencil m;
-
-  if (str == "||:")
-    str = "|:";
-
-  if (str == "|S" || str == "S|")
-    str = "S";
-
-  if (str == "")
-    {
-      Stencil empty = Lookup::blank (Box (Interval (0, 0), extent));
-      return empty;
-    }
-  else if (str == "|")
-    return thin;
-  else if (str == ".")
-    return thick;
-  else if (str == "|." || (h == 0 && str == ":|"))
-    {
-      m.add_at_edge (X_AXIS, LEFT, thick, 0);
-      m.add_at_edge (X_AXIS, LEFT, thin, kern);
-    }
-  else if (str == ".|" || (h == 0 && str == "|:"))
-    {
-      m.add_at_edge (X_AXIS, RIGHT, thick, 0);
-      m.add_at_edge (X_AXIS, RIGHT, thin, kern);
-    }
-  else if (str == ":|")
-    {
-      m.add_at_edge (X_AXIS, LEFT, thick, 0);
-      m.add_at_edge (X_AXIS, LEFT, thin, kern);
-      m.add_at_edge (X_AXIS, LEFT, colon, kern);
-    }
-  else if (str == "|:")
-    {
-      m.add_at_edge (X_AXIS, RIGHT, thick, 0);
-      m.add_at_edge (X_AXIS, RIGHT, thin, kern);
-      m.add_at_edge (X_AXIS, RIGHT, colon, kern);
-    }
-  else if (str == ":|:")
-    {
-      m.add_at_edge (X_AXIS, LEFT, thick, thinkern);
-      m.add_at_edge (X_AXIS, LEFT, colon, kern);
-      m.add_at_edge (X_AXIS, RIGHT, thick, kern);
-      m.add_at_edge (X_AXIS, RIGHT, colon, kern);
-    }
-  else if (str == ":|.|:")
-    {
-      m.add_at_edge (X_AXIS, LEFT, thick, 0);
-      m.add_at_edge (X_AXIS, LEFT, thin, kern);
-      m.add_at_edge (X_AXIS, LEFT, colon, kern);
-      m.add_at_edge (X_AXIS, RIGHT, thin, kern);
-      m.add_at_edge (X_AXIS, RIGHT, colon, kern);
-    }
-  else if (str == ":|.:")
-    {
-      m.add_at_edge (X_AXIS, LEFT, thick, 0);
-      m.add_at_edge (X_AXIS, LEFT, thin, kern);
-      m.add_at_edge (X_AXIS, LEFT, colon, kern);
-      m.add_at_edge (X_AXIS, RIGHT, colon, kern);
-    }
-  else if (str == ".|.")
-    {
-      m.add_at_edge (X_AXIS, LEFT, thick, thinkern);
-      m.add_at_edge (X_AXIS, RIGHT, thick, kern);
-    }
-  else if (str == "|.|")
-    {
-      m.add_at_edge (X_AXIS, LEFT, thick, 0);
-      m.add_at_edge (X_AXIS, LEFT, thin, kern);
-      m.add_at_edge (X_AXIS, RIGHT, thin, kern);
-    }
-  else if (str == "||")
-    {
-      /*
-        should align to other side? this never appears
-        on the system-start?
-        m.add_at_edge (X_AXIS, RIGHT, thin, 0);
-        m.add_at_edge (X_AXIS, RIGHT, thin, thinkern);
-      */
-      m.add_at_edge (X_AXIS, LEFT, thin, thinkern);
-      m.add_at_edge (X_AXIS, RIGHT, thin, thinkern);
-    }
-  else if (str.find ("S") != NPOS || str == "|._.|")
-    {
-      //  Handle all varsegno stuff
-      Stencil segno;
-      segno.add_at_edge (X_AXIS, LEFT, thin, thinkern);
-      segno.add_at_edge (X_AXIS, RIGHT, thin, thinkern);
-      segno.add_stencil (Font_interface::get_default_font (me)->find_by_name ("scripts.varsegno"));
-
-      if (str == "S")
-        m.add_stencil (segno);
-      else if (str == "S|:" || str == ".S|:")
-        {
-          m.add_at_edge (X_AXIS, RIGHT, thick, 0);
-          m.add_at_edge (X_AXIS, RIGHT, thin, kern);
-          m.add_at_edge (X_AXIS, RIGHT, colon, kern);
-          m.add_at_edge (X_AXIS, LEFT, segno, thinkern);
-        }
-      else if (str == ":|S" || str == ":|S.")
-        {
-          m.add_at_edge (X_AXIS, LEFT, thick, 0);
-          m.add_at_edge (X_AXIS, LEFT, thin, kern);
-          m.add_at_edge (X_AXIS, LEFT, colon, kern);
-          m.add_at_edge (X_AXIS, RIGHT, segno, thinkern);
-        }
-      else if (str == ":|S|:" || str == ":|S.|:")
-        {
-          m.add_at_edge (X_AXIS, LEFT, thick, 0);
-          m.add_at_edge (X_AXIS, LEFT, thin, kern);
-          m.add_at_edge (X_AXIS, LEFT, colon, kern);
-          m.add_at_edge (X_AXIS, RIGHT, segno, thinkern);
-          m.add_at_edge (X_AXIS, RIGHT, thick, thinkern);
-          m.add_at_edge (X_AXIS, RIGHT, thin, kern);
-          m.add_at_edge (X_AXIS, RIGHT, colon, kern);
-        }
-      else if (str == "|._.|") // :|S|: or :|S.|: without segno and colon
-        {
-          // get the width of the segno sign
-          Real segno_width = segno.extent (X_AXIS).length ();
-          m.add_at_edge (X_AXIS, LEFT, thick, 0);
-          m.add_at_edge (X_AXIS, LEFT, thin, kern);
-          m.add_at_edge (X_AXIS, RIGHT, thick, segno_width + 2 * thinkern);
-          m.add_at_edge (X_AXIS, RIGHT, thin, kern);
-        }
-      // end varsegno block
-    }
-  else if (str == ":")
-    {
-      if (Grob *staff = Staff_symbol_referencer::get_staff_symbol (me))
-        {
-          Interval staff_extent = staff->extent (staff, Y_AXIS);
-
-          /*
-            assume staff lines are disposed equally at unit space;
-            put a dot into each space within extent (may extend staff_extent).
-
-            staff_extent is an interval of two integers or two half-integers;
-            in the former case dots are to be placed at half-integers,
-            in the latter at integers.
-
-            these integers are not exact due to staff line thickness.
-          */
-          int const pos = int (rint (staff_extent.at (UP) * 2));
-          Real const correction = pos & 1 ? 0.0 : 0.5;
-
-          for (int i = int (rint (extent.at (DOWN) + (0.5 - correction))),
-               e = int (rint (extent.at (UP) + (0.5 - correction)));
-               i < e;
-               ++i)
-            {
-              Stencil d (dot);
-
-              d.translate_axis (i + correction, Y_AXIS);
-              m.add_stencil (d);
-            }
-        }
-    }
-  else if (str == "dashed")
-    m = dashed_bar_line (me, extent, hair);
-  else if (str == "'")
-    m = tick_bar_line (me, extent.at (UP), rounded);
-  else if (str == "kievan")
-   {
-    me->set_property ("layer", scm_from_int (1));
-    m.add_stencil (Font_interface::get_default_font (me)->find_by_name ("scripts.barline.kievan"));
-    m = *unsmob_stencil (scm_call_1 (ly_lily_module_constant ("stencil-whiteout"), m.smobbed_copy ()));
-   }
-  return m;
-}
-
-Stencil
-Bar_line::simple_barline (Grob *me,
-                          Real w,
-                          Interval const &extent,
-                          bool rounded)
-{
-  Real blot
-    = rounded
-      ? me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter"))
-      : 0.0;
-
-  return Lookup::round_filled_box (Box (Interval (0, w), extent), blot);
-}
-
-Stencil
-Bar_line::tick_bar_line (Grob *me, Real h, bool rounded)
-{
-  Real th = Staff_symbol_referencer::staff_space (me) / 2;
-  Real line_thick = Staff_symbol_referencer::line_thickness (me);
-
-  Real blot
-    = rounded
-      ? me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter"))
-      : 0.0;
-
-  return Lookup::round_filled_box (Box (Interval (0, line_thick),
-                                        Interval (h - th, h + th)), blot);
-}
-
-Stencil
-Bar_line::dashed_bar_line (Grob *me, Interval const &extent, Real thick)
-{
-  Real dash_size
-    = 1.0 - robust_scm2double (me->get_property ("gap"), 0.3);
-  /*
-    this is a tad complex for what we want to achieve, but with a
-    simple line, the round blotting interferes with staff line
-    connections.
-  */
-  Real ss = Staff_symbol_referencer::staff_space (me);
-  Real const h = extent.length ();
-  int dashes = int (rint (h / ss));
-
-  /*
-    there are two concerns:
-    1. one dash plus one space should be one staff space
-    2. the line should begin and end with half a dash
-
-    both can be satisfied, if the extent is (roughly) an integer
-    multiple of staff space.
-  */
-  if (fabs (h / ss - dashes) < 0.1)
-    {
-      Real blot
-        = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter"));
-
-      Real const half_dash = dash_size / 2;
-      Stencil bar;
-
-      for (int i = 0; i <= dashes; ++i)
-        {
-          Real top_y = extent.at (DOWN)
-                       + (i == dashes ? h : (i + half_dash) * ss);
-          Real bot_y = extent.at (DOWN) + (i ? (i - half_dash) * ss : 0.0);
-
-          bar.add_stencil (Lookup::round_filled_box (Box (Interval (0, thick),
-                                                          Interval (bot_y, top_y)),
-                                                     blot));
-        }
-      return bar;
-    }
-  else
-    {
-      /*
-        We have to scale the dashing so it starts and ends with half a
-        dash exactly.
-      */
-      Real total_dash_size = h / dashes;
-      Real factor = (dash_size - thick) / ss;
-
-      SCM at = scm_list_n (ly_symbol2scm ("dashed-line"),
-                           scm_from_double (thick),
-                           scm_from_double (factor * total_dash_size),
-                           scm_from_double ((1 - factor) * total_dash_size),
-                           scm_from_double (0),
-                           scm_from_double (h),
-                           scm_from_double (factor * total_dash_size * 0.5),
-                           SCM_UNDEFINED);
-
-      Box box;
-      box.add_point (Offset (0, 0));
-      box.add_point (Offset (0, h));
-
-      Stencil s (box, at);
-      s.translate (Offset (thick / 2, extent.at (DOWN)));
-      return s;
-    }
-  return Stencil ();
-}
-
-MAKE_SCHEME_CALLBACK (Bar_line, calc_anchor, 1)
-SCM
-Bar_line::calc_anchor (SCM smob)
-{
-  Grob *me = unsmob_grob (smob);
-  Real kern = robust_scm2double (me->get_property ("kern"), 1);
-  Real staffline = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness"));
-  string str = robust_scm2string (me->get_property ("glyph-name"), "");
-
-  /* we put the anchor in the center of the barline, unless we are
-     a repeat bar, in which case we put the anchor in the center of
-     the barline without the dots. */
-  Interval ext = me->extent (me, X_AXIS);
-  if (ext.is_empty ())
-    return scm_from_double (0);
-
-  Real anchor = ext.center ();
-
-  Stencil dot = Font_interface::get_default_font (me)->find_by_name ("dots.dot");
-  Real dot_width = dot.extent (X_AXIS).length () + kern * staffline;
-  if (str == "|:")
-    anchor -= dot_width / 2;
-  else if (str == ":|")
-    anchor += dot_width / 2;
-
-  return scm_from_double (anchor);
-}
-
-ADD_INTERFACE (Bar_line,
-               "Bar line.\n"
-               "\n"
-               "Print a special bar symbol.  It replaces the regular bar"
-               " symbol with a special symbol.  The argument @var{bartype}"
-               " is a string which specifies the kind of bar line to print."
-               "  Options are @code{|}, @code{:|}, @code{|:}, @code{:|:}, @code{:|.|:},"
-               " @code{:|.:}, @code{.}, @code{||}, @code{|.}, @code{.|}, @code{.|.},"
-               " @code{|.|}, @code{:}, @code{dashed}, @code{'} and @code{S}.\n"
-               "\n"
-               "These produce, respectively, a normal bar line, a right repeat, a left repeat,"
-               " a thick double repeat, a thin-thick-thin double repeat,"
-               " a thin-thick double repeat, a thick bar, a double bar, a start bar,"
-               " an end bar, a thick double bar, a thin-thick-thin bar,"
-               " a dotted bar, a dashed bar, a tick as bar line and a segno bar.\n"
-               "\n"
-               "In addition, there is an option"
-               " @code{||:} which is equivalent to @code{|:} except at line"
-               " breaks, where it produces a double bar (@code{||}) at the"
-               " end of the line and a repeat sign (@code{|:}) at the"
-               " beginning of the new line.\n"
-               "\n"
-               "For segno, @code{S} produces a segno sign except at line breaks,"
-               " where it produces a double bar (@code{||}) at the"
-               " end of the line and a segno sign at the beginning of the new line."
-               " @code{|S} is equivalent to @code{S} but produces a simple bar line"
-               " (@code{|}) instead of a double bar line (@code{||}) at line breaks."
-               " @code{S|} produces the segno sign at line breaks and starts the following"
-               " line without special bar lines.\n"
-               "\n"
-               "@code{S|:} and @code{:|S} are used for repeat/segno combinations that are"
-               " separated at line breaks.  Alternatively, @code{.S|:} and @code{:|S.}"
-               " may be used which combine repeat signs and segno at the same line in"
-               " case of a line break.  @code{:|S|:} is a combination of a left repeat"
-               " (@code{:|}), a segno (@code{S}) and a right repeat @code{|:} which"
-               " splits before the segno at line breaks; @code{:|S.|:} splits after"
-               " the segno sign.\n"
-               "\n"
-               "If @var{bartype} is set to @code{empty} then nothing is"
-               " printed, but a line break is allowed at that spot.\n"
-               "\n"
-               "@code{gap} is used for the gaps in dashed bar lines.",
-
-               /* properties */
-               "allow-span-bar "
-               "gap "
-               "kern "
-               "thin-kern "
-               "hair-thickness "
-               "has-span-bar "
-               "thick-thickness "
-               "glyph "
-               "glyph-name "
-               "bar-extent "
-              );
index 29fb3f0bdc028ae3fdc86704c847530f829c5b7d..00c345771728f4e46a06ed75ce08c023b0740f1c 100644 (file)
@@ -23,7 +23,6 @@ using namespace std;
 
 #include "item.hh"
 #include "context.hh"
-#include "bar-line.hh"
 #include "staff-symbol-referencer.hh"
 #include "engraver.hh"
 #include "direction.hh"
index c5d8ea6dba83292624df491957c6a311c284154c..dad382a27a64d9c85612ad67d7e7f753daa8f166 100644 (file)
@@ -24,7 +24,6 @@ using namespace std;
 
 #include "item.hh"
 #include "context.hh"
-#include "bar-line.hh"
 #include "staff-symbol-referencer.hh"
 #include "engraver.hh"
 #include "direction.hh"
index c6ad98aa02984fb1b3d8f4c8eecd4c135d248387..6b915f5cb45114851b4a513730048dc6bfe126db 100644 (file)
@@ -19,7 +19,6 @@
 */
 
 #include "engraver.hh"
-#include "bar-line.hh"
 #include "item.hh"
 #include "note-head.hh"
 #include "pitch.hh"
index e56e02d27a40c2e709d4ba18ad72df086005a48c..81ff7864ff36b4b4ff972bb0fc3051d8700f60e5 100644 (file)
@@ -453,3 +453,16 @@ LY_DEFINE (ly_grob_chain_callback, "ly:grob-chain-callback",
   chain_callback (gr, proc, sym);
   return SCM_UNSPECIFIED;
 }
+
+LY_DEFINE (ly_grob_vertical_less_p, "ly:grob-vertical<?",
+           2, 0, 0, (SCM a, SCM b),
+           "Does @var{a} lie above @var{b} on the page?")
+{
+  LY_ASSERT_SMOB (Grob, a, 1);
+  LY_ASSERT_SMOB (Grob, b, 2);
+
+  Grob *ga = unsmob_grob (a);
+  Grob *gb = unsmob_grob (b);
+
+  return ly_bool2scm (Grob::vertical_less (ga, gb));
+}
index 3933bd8a3b458c23ed4282f2f9cd4f8cf0334c76..cacfb0f51c148968f015fec995ef17d742ba24b3 100644 (file)
@@ -20,7 +20,6 @@
 #include "hairpin.hh"
 
 #include "axis-group-interface.hh"
-#include "bar-line.hh"
 #include "dimensions.hh"
 #include "directional-element-interface.hh"
 #include "international.hh"
@@ -82,7 +81,7 @@ Hairpin::broken_bound_padding (SCM smob)
     {
       extract_grob_set (vertical_axis_groups[d], "elements", elts);
       for (vsize i = elts.size (); i--;)
-        if (Bar_line::has_interface (elts[i])
+        if (elts[i]->internal_has_interface (ly_symbol2scm ("bar-line-interface"))
             && dynamic_cast<Item *> (elts[i])->break_status_dir () == -1)
           {
             SCM hsb = elts[i]->get_property ("has-span-bar");
@@ -92,6 +91,7 @@ Hairpin::broken_bound_padding (SCM smob)
             span_bars[d] = unsmob_grob ((d == UP ? scm_car : scm_cdr) (hsb));
             break;
           }
+
       if (!span_bars[d])
         return scm_from_double (0.0);
     }
index 432cb0fd4a2be9e2e9c262bab9e6561834a57198..8f7b1a24dd0a0a9fe23bd04631ea17a88f92d757 100644 (file)
@@ -28,17 +28,6 @@ class Bar_line
 public:
   DECLARE_GROB_INTERFACE ();
 
-  static Stencil dashed_bar_line (Grob *me, Interval const &extent, Real thick);
-  static Stencil tick_bar_line (Grob *me, Real h, bool rounded);
-  static Stencil compound_barline (Grob *, string, Interval const &extent,
-                                   bool rounded);
-  static Stencil simple_barline (Grob *, Real wid, Interval const &extent,
-                                 bool rounded);
-  static Interval bar_y_extent (Grob *, Grob *);
   static bool non_empty_barline (Grob *me);
-
-  DECLARE_SCHEME_CALLBACK (calc_bar_extent, (SCM));
-  DECLARE_SCHEME_CALLBACK (print, (SCM));
-  DECLARE_SCHEME_CALLBACK (calc_anchor, (SCM));
 };
 #endif // BAR_LINE_HH
diff --git a/lily/include/span-bar.hh b/lily/include/span-bar.hh
deleted file mode 100644 (file)
index 6ae9dc1..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-  This file is part of LilyPond, the GNU music typesetter.
-
-  Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
-
-  LilyPond is free software: you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation, either version 3 of the License, or
-  (at your option) any later version.
-
-  LilyPond is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef SPAN_BAR_HH
-#define SPAN_BAR_HH
-
-#include "lily-proto.hh"
-#include "grob-interface.hh"
-
-/**
-   This is a barline that is spanned across other bar lines.  This is
-   the implementation of the long barlines that occur in orchestral
-   score and other multi-staff music.
-*/
-class Span_bar
-{
-public:
-
-  DECLARE_GROB_INTERFACE ();
-  static Interval get_spanned_interval (Grob *);
-  static void add_bar (Grob *, Grob *);
-  static void evaluate_glyph (Grob *);
-  static void notify_grobs_of_my_existence (Grob *);
-  DECLARE_SCHEME_CALLBACK (width, (SCM smob));
-  DECLARE_SCHEME_CALLBACK (print, (SCM));
-  DECLARE_SCHEME_CALLBACK (calc_glyph_name, (SCM));
-  DECLARE_SCHEME_CALLBACK (before_line_breaking, (SCM));
-  DECLARE_SCHEME_CALLBACK (center_on_spanned_callback, (SCM element));
-};
-
-#endif // SPAN_BAR_HH
index 6f1d9a374e4fb64fbffa24e5c5628e25026aee2d..5707b548b99f46e8923a99bd710115d06381e2e6 100644 (file)
@@ -17,7 +17,6 @@
   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "bar-line.hh"
 #include "clef.hh"
 #include "context.hh"
 #include "engraver.hh"
index 4f2cd630d21edbbd4ea7d141f6d84bcb352e04b2..25b19bd18a607b2ae34e50e9c7e677242dbcb922 100644 (file)
@@ -23,7 +23,6 @@ using namespace std;
 #include "engraver.hh"
 
 #include "axis-group-interface.hh"
-#include "bar-line.hh"
 #include "context.hh"
 #include "grob-array.hh"
 #include "international.hh"
index dc22f904844af91e488aea7eacb03e7ed558abf2..09c846f8968c1c9897d040e1740555da145a70b0 100644 (file)
   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "bar-line.hh"
 #include "item.hh"
-#include "span-bar.hh"
 #include "engraver.hh"
+#include "pointer-group-interface.hh"
 
 /**
 
@@ -54,7 +53,7 @@ void
 Span_bar_engraver::acknowledge_bar_line (Grob_info i)
 {
   int depth = i.origin_contexts (this).size ();
-  if (depth && !Span_bar::has_interface (i.grob ()))
+  if (depth && !i.grob ()->internal_has_interface (ly_symbol2scm ("span-bar-interface")))
     {
       Item *it = dynamic_cast<Item *> (i.grob ());
       bars_.push_back (it);
@@ -73,7 +72,7 @@ Span_bar_engraver::process_acknowledged ()
 
       spanbar_->set_parent (bars_[0], X_AXIS);
       for (vsize i = 0; i < bars_.size (); i++)
-        Span_bar::add_bar (spanbar_, bars_[i]);
+        Pointer_group_interface::add_grob (spanbar_, ly_symbol2scm ("elements"), bars_[i]);
       make_spanbar_ = false;
     }
 }
@@ -87,7 +86,7 @@ Span_bar_engraver::stop_translation_timestep ()
       SCM vis = bars_[0]->internal_get_property (vissym);
       if (ly_is_equal (spanbar_->internal_get_property (vissym), vis))
         spanbar_->set_property (vissym, vis);
-      Span_bar::notify_grobs_of_my_existence (spanbar_);
+      scm_call_1 (ly_lily_module_constant ("span-bar::notify-grobs-of-my-existence"), spanbar_->self_scm ());
       spanbar_ = 0;
     }
   bars_.resize (0);
index 11f1137f2f28278f679b807e558d609831ca9f2e..10d97241bde43c0563d749074c845eb4ca54fcec 100644 (file)
 #include <algorithm>
 
 #include "align-interface.hh"
-#include "bar-line.hh"
 #include "context.hh"
 #include "grob.hh"
 #include "item.hh"
 #include "pointer-group-interface.hh"
-#include "span-bar.hh"
 #include "engraver.hh"
 
 /*
diff --git a/lily/span-bar.cc b/lily/span-bar.cc
deleted file mode 100644 (file)
index 5652313..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
-  This file is part of LilyPond, the GNU music typesetter.
-
-  Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
-
-  LilyPond is free software: you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation, either version 3 of the License, or
-  (at your option) any later version.
-
-  LilyPond is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "span-bar.hh"
-
-#include "font-interface.hh"
-#include "dimensions.hh"
-#include "output-def.hh"
-#include "stencil.hh"
-#include "warn.hh"
-#include "axis-group-interface.hh"
-#include "bar-line.hh"
-#include "grob.hh"
-#include "pointer-group-interface.hh"
-#include "staff-symbol-referencer.hh"
-
-void
-Span_bar::add_bar (Grob *me, Grob *b)
-{
-  Pointer_group_interface::add_grob (me, ly_symbol2scm ("elements"), b);
-}
-
-MAKE_SCHEME_CALLBACK (Span_bar, print, 1);
-
-/* Limitations/Bugs:
-
-(1) Elements from 'me->get_object ("elements")' must be
-ordered according to their y coordinates relative to their common
-axis group parent.  Otherwise, the computation goes mad.
-
-(2) This method depends on bar_engraver not being removed from
-staff context.  If bar_engraver is removed, the size of the staff
-lines is evaluated as 0, which results in a solid span bar line
-with faulty y coordinate. */
-
-/* This routine was originally by Juergen Reuter, but it was a on the
-   bulky side. Rewritten by Han-Wen. */
-SCM
-Span_bar::print (SCM smobbed_me)
-{
-  Grob *me = unsmob_grob (smobbed_me);
-  extract_grob_set (me, "elements", elements);
-  Grob *refp = common_refpoint_of_array (elements, me, Y_AXIS);
-
-  SCM glyph = me->get_property ("glyph-name");
-
-  /* glyph may not be a string, when ME is killed by Hara Kiri in
-     between. */
-  if (!scm_is_string (glyph))
-    return SCM_EOL;
-
-  string glyph_string = ly_scm2string (glyph);
-
-  /* compose span_bar_mol */
-  vector<Interval> extents;
-  vector<bool> make_span_bar;
-  Grob *model_bar = 0;
-  for (vsize i = elements.size (); i--;)
-    {
-      Grob *bar = elements[i];
-      Interval ext = Bar_line::bar_y_extent (bar, refp);
-      if (Grob *staff = Staff_symbol_referencer::get_staff_symbol (bar))
-        ext.unite (staff->extent (refp, Y_AXIS));
-      if (ext.is_empty ())
-        continue;
-
-      extents.push_back (ext);
-      make_span_bar.push_back (to_boolean (bar->get_property ("allow-span-bar")));
-      model_bar = bar;
-    }
-
-  if (!model_bar)
-    model_bar = me;
-
-  // Fixes problem with disappearing span bars when alignAboveContext is active
-  vector_sort (extents, Interval::left_less);
-
-  Stencil span_bar;
-  for (vsize i = 1; i < extents.size (); i++)
-    {
-      Interval prev_extent = extents[i - 1];
-      Interval ext = extents[i];
-      if (!prev_extent.is_empty ())
-        {
-          Interval l (prev_extent [UP],
-                      ext[DOWN]);
-
-          if (l.is_empty () || !make_span_bar[i])
-            {
-              /* There is overlap between the bar lines.  Do nothing. */
-            }
-          else
-            {
-              Stencil interbar = Bar_line::compound_barline (model_bar,
-                                                             glyph_string,
-                                                             l,
-                                                             false);
-              span_bar.add_stencil (interbar);
-            }
-        }
-      prev_extent = ext;
-    }
-
-  span_bar.translate_axis (- me->relative_coordinate (refp, Y_AXIS),
-                           Y_AXIS);
-
-  return span_bar.smobbed_copy ();
-}
-
-MAKE_SCHEME_CALLBACK (Span_bar, width, 1);
-SCM
-Span_bar::width (SCM smob)
-{
-  Grob *me = unsmob_grob (smob);
-  SCM gn = me->get_property ("glyph-name");
-  if (!me->is_live ())
-    return ly_interval2scm (Interval ());
-
-  string gl = ly_scm2string (gn);
-
-  /*
-    urg.
-  */
-  Stencil m
-    = Bar_line::compound_barline (me, gl, Interval (-20 PT, 20 PT), false);
-
-  return ly_interval2scm (m.extent (X_AXIS));
-}
-
-MAKE_SCHEME_CALLBACK (Span_bar, before_line_breaking, 1);
-SCM
-Span_bar::before_line_breaking (SCM smob)
-{
-  Grob *me = unsmob_grob (smob);
-  extract_grob_set (me, "elements", elements);
-  if (elements.empty ())
-    me->suicide ();
-
-  return SCM_UNSPECIFIED;
-}
-
-MAKE_SCHEME_CALLBACK (Span_bar, center_on_spanned_callback, 1);
-
-SCM
-Span_bar::center_on_spanned_callback (SCM smob)
-{
-  Grob *me = unsmob_grob (smob);
-  Interval i (get_spanned_interval (me));
-
-  /* Bar_line::print delivers a barline of y-extent (-h/2, h/2), so
-     we have to translate ourselves to be in the center of the
-     interval that we span. */
-  if (i.is_empty ())
-    {
-      me->suicide ();
-      return scm_from_double (0.0);
-    }
-
-  return scm_from_double (i.center ());
-}
-
-MAKE_SCHEME_CALLBACK (Span_bar, calc_glyph_name, 1);
-SCM
-Span_bar::calc_glyph_name (SCM smob)
-{
-  Grob *me = unsmob_grob (smob);
-  extract_grob_set (me, "elements", elements);
-  SCM gl = SCM_EOL;
-  for (vsize i = elements.size ();
-       i-- && !scm_is_string (gl);)
-    gl = elements[i]->get_property ("glyph-name");
-
-  if (!scm_is_string (gl))
-    {
-      me->suicide ();
-      return SCM_UNSPECIFIED;
-    }
-
-  string type = ly_scm2string (gl);
-  if (type == "|:" || type == "||:")
-    type = ".|";
-  else if (type == ":|")
-    type = "|.";
-  else if (type == ":|:")
-    type = ".|.";
-  else if (type == ":|.|:")
-    type = "|.|";
-  else if (type == ":|.:")
-    type = "|.";
-  else if (type == "S" || type == "S|" || type == "|S")
-    type = "||";
-  else if (type == "S|:" || type == ".S|:")
-    type = ".|";
-  else if (type == ":|S" || type == ":|S.")
-    type = "|.";
-  else if (type == ":|S|:" || type == ":|S.|:")
-    type = "|._.|";
-  else if (type == "'")
-    type = "";
-
-  return ly_string2scm (type);
-}
-
-void
-Span_bar::notify_grobs_of_my_existence (Grob *me)
-{
-  extract_grob_set (me, "elements", elts);
-  vector<Grob *> sortable (elts.begin (), elts.end ());
-  vector_sort (sortable, Grob::vertical_less);
-  for (vsize i = 0; i < sortable.size (); i++)
-    sortable[i]->set_property ("has-span-bar",
-                               scm_cons (i != sortable.size () - 1 ? me->self_scm () : scm_from_bool (false),
-                                         i != 0 ? me->self_scm () : scm_from_bool (false)));
-}
-
-Interval
-Span_bar::get_spanned_interval (Grob *me)
-{
-  return ly_scm2interval (Axis_group_interface::generic_group_extent (me, Y_AXIS));
-}
-
-ADD_INTERFACE (Span_bar,
-               "A bar line that is spanned between other barlines.  This"
-               " interface is used for bar lines that connect different"
-               " staves.",
-
-               /* properties */
-               "glyph-name "
-               "elements "
-               "pure-Y-common "
-               "pure-relevant-grobs "
-               "pure-relevant-items "
-               "pure-relevant-spanners "
-              );
-
index d348b10fd7347699ade91628563da97068423f6a..49f42ea4a6d3e4caa98f3c8b75a795825bbf5f7d 100644 (file)
@@ -26,7 +26,6 @@ using namespace std;
 #include "paper-column.hh"
 #include "separation-item.hh"
 #include "warn.hh"
-#include "bar-line.hh"
 #include "staff-symbol-referencer.hh"
 #include "note-column.hh"
 #include "stem.hh"
@@ -75,7 +74,8 @@ Staff_spacing::bar_y_positions (Grob *bar_grob)
 {
   Interval bar_size;
   bar_size.set_empty ();
-  if (Bar_line::has_interface (bar_grob))
+
+  if (bar_grob->internal_has_interface (ly_symbol2scm ("bar-line-interface")))
     {
       SCM glyph = bar_grob->get_property ("glyph-name");
       Grob *staff_sym = Staff_symbol_referencer::get_staff_symbol (bar_grob);
index 520a1225c4be95a0cea3ff483d88dbf9b6bcd068..97f14fdce03b0e6f88aecac0be7ccc4491e0938f 100644 (file)
@@ -20,7 +20,6 @@
 #include "context.hh"
 #include "paper-column.hh"
 #include "align-interface.hh"
-#include "span-bar.hh"
 #include "axis-group-interface.hh"
 #include "engraver.hh"
 #include "spanner.hh"
index f4dc48bf642c699ea01b8ae5ae3f35fafbf528bd..882359621ab63ea6ffa4276dc16648ca5e626a7b 100644 (file)
@@ -20,7 +20,6 @@
 #include "engraver.hh"
 
 #include "axis-group-interface.hh"
-#include "bar-line.hh"
 #include "context.hh"
 #include "grob-array.hh"
 #include "international.hh"
diff --git a/scm/bar-line.scm b/scm/bar-line.scm
new file mode 100644 (file)
index 0000000..e000178
--- /dev/null
@@ -0,0 +1,650 @@
+;;;; This file is part of LilyPond, the GNU music typesetter.
+;;;;
+;;;; Copyright (C) 2009--2012 Marc Hohl <marc@hohlart.de>
+;;;;
+;;;; LilyPond is free software: you can redistribute it and/or modify
+;;;; it under the terms of the GNU General Public License as published by
+;;;; the Free Software Foundation, either version 3 of the License, or
+;;;; (at your option) any later version.
+;;;;
+;;;; LilyPond is distributed in the hope that it will be useful,
+;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;;; GNU General Public License for more details.
+;;;;
+;;;; You should have received a copy of the GNU General Public License
+;;;; along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
+
+;; helper functions
+
+(define (get-staff-symbol grob)
+  (if (grob::has-interface grob 'staff-symbol-interface)
+      grob
+      (ly:grob-object grob 'staff-symbol)))
+
+(define (layout-blot-diameter grob)
+  (let* ((layout (ly:grob-layout grob))
+         (blot (ly:output-def-lookup layout 'blot-diameter)))
+
+        blot))
+
+(define (layout-line-thickness grob)
+  (let* ((layout (ly:grob-layout grob))
+         (line-thickness (ly:output-def-lookup layout 'line-thickness)))
+
+        line-thickness))
+
+(define (staff-symbol-line-count grob)
+  (let ((line-count 0))
+
+       (if (ly:grob? grob)
+           (let ((line-pos (ly:grob-property grob 'line-positions '())))
+
+                (set! line-count (if (pair? line-pos)
+                                     (length line-pos)
+                                     (ly:grob-property grob 'line-count 0)))))
+
+         line-count))
+
+(define (staff-symbol-line-span grob)
+  (let ((line-pos (ly:grob-property grob 'line-positions '()))
+        (iv (cons 0.0 0.0)))
+
+       (if (pair? line-pos)
+           (map (lambda (x)
+                        (set! iv (cons (min (car iv) x)
+                                       (max (cdr iv) x))))
+                line-pos)
+           (let ((line-count (ly:grob-property grob 'line-count 0)))
+
+                (set! iv (cons (- 1 line-count)
+                               (- line-count 1)))))
+       iv))
+
+(define (staff-symbol-line-positions grob)
+  (let ((line-pos (ly:grob-property grob 'line-positions '())))
+
+       (if (not (pair? line-pos))
+           (let* ((line-count (ly:grob-property grob 'line-count 0))
+                  (height (- line-count 1.0)))
+
+                 (set! line-pos (map (lambda (x)
+                                             (- height (* x 2)))
+                                     (iota line-count)))))
+       line-pos))
+
+;; functions used by external routines
+
+(define-public (span-bar::notify-grobs-of-my-existence grob)
+  (let* ((elts (ly:grob-array->list (ly:grob-object grob 'elements)))
+         (sorted-elts (sort elts ly:grob-vertical<?))
+         (last-pos (1- (length sorted-elts)))
+         (idx 0))
+
+        (map (lambda (g)
+                     (ly:grob-set-property!
+                       g
+                       'has-span-bar
+                       (cons (if (eq? idx last-pos)
+                                 #f
+                                 grob)
+                             (if (zero? idx)
+                                 #f
+                                 grob)))
+                      (set! idx (1+ idx)))
+             sorted-elts)))
+
+;; How should a bar line behave at a break?
+;; the following alist has the form
+;; ( unbroken-bar-glyph . ( bar-glyph-at-end-of-line . bar-glyph-at-begin-of-line ))
+
+(define bar-glyph-alist
+  '((":|:" . (":|" . "|:"))
+    (":|.|:" . (":|" . "|:"))
+    (":|.:" . (":|" . "|:"))
+    ("||:" . ("||" . "|:"))
+    ("dashed" . ("dashed" . '()))
+    ("|" . ("|" . ()))
+    ("|s" . (() . "|"))
+    ("|:" . ("|" . "|:"))
+    ("|." . ("|." . ()))
+
+    ;; hmm... should we end with a bar line here?
+    (".|" . ("|" . ".|"))
+    (":|" . (":|" . ()))
+    ("||" . ("||" . ()))
+    (".|." . (".|." . ()))
+    ("|.|" . ("|.|" . ()))
+    ("" . ("" . ""))
+    (":" . (":" . ""))
+    ("." . ("." . ()))
+    ("'" . ("'" . ()))
+    ("empty" . (() . ()))
+    ("brace" . (() . "brace"))
+    ("bracket" . (() . "bracket"))
+
+    ;; segno bar lines
+    ("S" . ("||" . "S"))
+    ("|S" . ("|" . "S"))
+    ("S|" . ("S" . ()))
+    (":|S" . (":|" . "S"))
+    (":|S." . (":|S" . ()))
+    ("S|:" . ("S" . "|:"))
+    (".S|:" . ("|" . "S|:"))
+    (":|S|:" . (":|" . "S|:"))
+    (":|S.|:" . (":|S" . "|:"))
+
+    ;; ancient bar lines
+    ("kievan" . ("kievan" . ""))))
+
+;; drawing functions for various bar line types
+
+(define (make-empty-bar-line grob extent)
+  (ly:make-stencil "" (cons 0 0) extent))
+
+(define (make-simple-bar-line grob width extent rounded)
+  (let ((blot (if rounded
+                  (layout-blot-diameter grob)
+                  0)))
+
+        (ly:round-filled-box (cons 0 width)
+                             extent
+                             blot)))
+
+(define (make-tick-bar-line grob height rounded)
+  (let ((half-staff (* 1/2 (ly:staff-symbol-staff-space grob)))
+        (staff-line-thickness (ly:staff-symbol-line-thickness grob))
+        (blot (if rounded
+                  (layout-blot-diameter grob)
+                  0)))
+
+       (ly:round-filled-box (cons 0 staff-line-thickness)
+                            (cons (- height half-staff) (+ height half-staff))
+                            blot)))
+
+(define (make-colon-bar-line grob)
+  (let* ((staff-space (ly:staff-symbol-staff-space grob))
+         (dot (ly:font-get-glyph (ly:grob-default-font grob) "dots.dot"))
+         (staff-symbol (get-staff-symbol grob))
+         (lines (staff-symbol-line-count staff-symbol))
+         (stencil empty-stencil)
+         (dist (* (if (or (odd? lines)
+                          (zero? lines))
+                      1
+                      (if (< staff-space 2)
+                          2
+                          0.5))
+                  staff-space)))
+
+        (if (zero? staff-space)
+            (set! staff-space 1.0))
+
+        (let* ((stencil (ly:stencil-add stencil dot))
+               (stencil (ly:stencil-translate-axis
+                          stencil dist Y))
+               (stencil (ly:stencil-add stencil dot))
+               (stencil (ly:stencil-translate-axis
+                          stencil (/ dist -2) Y)))
+              stencil)))
+
+(define (make-dotted-bar-line grob extent)
+  (let* ((position (round (* (interval-end extent) 2)))
+         (correction (if (even? position) 0.5 0.0))
+         (dot (ly:font-get-glyph (ly:grob-default-font grob) "dots.dot"))
+         (i (round (+ (interval-start extent)
+                      (- 0.5 correction))))
+         (e (round (+ (interval-end extent)
+                      (- 0.5 correction))))
+         (counting (interval-length (cons i e)))
+         (stil-list (map
+                      (lambda (x)
+                              (ly:stencil-translate-axis
+                                dot (+ x correction) Y))
+                      (iota counting i 1))))
+
+        (define (add-stencils! stil l)
+          (if (null? l)
+              stil
+              (if (null? (cdr l))
+                  (ly:stencil-add stil (car l))
+                  (add-stencils! (ly:stencil-add stil (car l)) (cdr l)))))
+
+        (add-stencils! empty-stencil stil-list)))
+
+(define (make-dashed-bar-line grob extent thickness)
+  (let* ((height (interval-length extent))
+         (staff-symbol (get-staff-symbol grob))
+         (staff-space (ly:staff-symbol-staff-space grob))
+         (line-thickness (layout-line-thickness grob))
+         (dash-size (- 1.0 (ly:grob-property grob 'gap 0.3)))
+         (line-count (staff-symbol-line-count staff-symbol)))
+
+        (if (< (abs (+ line-thickness
+                       (* (1- line-count) staff-space)
+                       (- height)))
+               0.1)
+            (let ((blot (layout-blot-diameter grob))
+                  (half-space (/ staff-space 2.0))
+                  (half-thick (/ line-thickness 2.0))
+                  (stencil empty-stencil))
+
+                 (map (lambda (i)
+                      (let ((top-y (min (* (+ i dash-size) half-space)
+                                        (+ (* (1- line-count) half-space)
+                                           half-thick)))
+                            (bot-y (max (* (- i dash-size) half-space)
+                                        (- 0 (* (1- line-count) half-space)
+                                           half-thick))))
+
+                           (set! stencil
+                                 (ly:stencil-add
+                                   stencil
+                                   (ly:round-filled-box (cons 0 thickness)
+                                                        (cons bot-y top-y)
+                                                        blot)))))
+                      (iota line-count (1- line-count) (- 2)))
+            stencil)
+            (let* ((dashes (/ height staff-space))
+                   (total-dash-size (/ height dashes))
+                   (factor (/ (- dash-size thickness) staff-space)))
+
+                  (ly:stencil-translate-axis
+                    (ly:make-stencil (list 'dashed-line
+                                           thickness
+                                           (* factor total-dash-size)
+                                           (* (- 1 factor) total-dash-size)
+                                           0
+                                           height
+                                           (* factor total-dash-size 0.5))
+                                           (cons 0 thickness)
+                                           (cons 0 height))
+                                           (interval-start extent)
+                                           Y)))))
+
+(define (make-segno-bar-line grob glyph extent rounded)
+  (let* ((line-thickness (layout-line-thickness grob))
+         (kern (* (ly:grob-property grob 'kern 1) line-thickness))
+         (thinkern (* (ly:grob-property grob 'thin-kern 1) line-thickness))
+         (hair (* (ly:grob-property grob 'hair-thickness 1) line-thickness))
+         (fatline (* (ly:grob-property grob 'thick-thickness 1) line-thickness))
+         (thin-stil (make-simple-bar-line grob hair extent rounded))
+         (thick-stil (make-simple-bar-line grob fatline extent rounded))
+         (colon-stil (make-colon-bar-line grob))
+         (segno-stil (ly:stencil-add
+                       (ly:stencil-combine-at-edge
+                         (ly:stencil-combine-at-edge
+                           '() X LEFT thin-stil thinkern)
+                         X RIGHT thin-stil thinkern)
+                       (ly:font-get-glyph (ly:grob-default-font grob) "scripts.varsegno")))
+         (glyph (cond
+                  ((string=? glyph "|S") "S")
+                  ((string=? glyph "S|") "S")
+                  (else glyph)))
+         (stencil (cond
+                    ((or (string=? glyph "S|:")
+                         (string=? glyph ".S|:"))
+                     (ly:stencil-combine-at-edge
+                       (ly:stencil-combine-at-edge
+                         (ly:stencil-combine-at-edge
+                           thick-stil X RIGHT thin-stil kern)
+                         X RIGHT colon-stil kern)
+                       X LEFT segno-stil thinkern))
+                    ((or (string=? glyph ":|S")
+                         (string=? glyph ":|S."))
+                     (ly:stencil-combine-at-edge
+                       (ly:stencil-combine-at-edge
+                         (ly:stencil-combine-at-edge
+                           thick-stil X LEFT thin-stil kern)
+                         X LEFT colon-stil kern)
+                       X RIGHT segno-stil thinkern))
+                    ((or (string=? glyph ":|S|:")
+                         (string=? glyph ":|S.|:"))
+                     (ly:stencil-combine-at-edge
+                       (ly:stencil-combine-at-edge
+                         (ly:stencil-combine-at-edge
+                           (ly:stencil-combine-at-edge
+                             (ly:stencil-combine-at-edge
+                               (ly:stencil-combine-at-edge
+                                 thick-stil X LEFT thin-stil kern)
+                               X LEFT colon-stil kern)
+                             X RIGHT segno-stil thinkern)
+                           X RIGHT thick-stil thinkern)
+                         X RIGHT thin-stil kern)
+                       X RIGHT colon-stil kern))
+                    ((string=? glyph "|._.|")
+                     (ly:stencil-combine-at-edge
+                       (ly:stencil-combine-at-edge
+                         (ly:stencil-combine-at-edge
+                           thick-stil X LEFT thin-stil kern)
+                         X RIGHT thick-stil (+ (interval-length
+                                                 (ly:stencil-extent segno-stil X))
+                                               (* 2 thinkern)))
+                       X RIGHT thin-stil kern))
+                    (else segno-stil))))
+
+       stencil))
+
+(define (make-kievan-bar-line grob)
+  (let* ((font (ly:grob-default-font grob))
+         (stencil (stencil-whiteout
+                    (ly:font-get-glyph font "scripts.barline.kievan"))))
+
+        ;; the kievan bar line has mo staff lines underneath,
+        ;; so we whiteout them and move ithe grob to a higher layer
+        (ly:grob-set-property! grob 'layer 1)
+        stencil))
+
+;; bar line callbacks
+
+(define-public (ly:bar-line::calc-bar-extent grob)
+  (let ((staff-symbol (get-staff-symbol grob))
+        (staff-extent (cons 0 0)))
+
+       (if (ly:grob? staff-symbol)
+           (let* ((bar-line-color (ly:grob-property grob 'color))
+                  (staff-color (ly:grob-property staff-symbol 'color))
+                  (radius (ly:staff-symbol-staff-radius grob))
+                  (staff-line-thickness (ly:staff-symbol-line-thickness grob)))
+
+                 ;; Due to rounding problems, bar lines extending to the outermost edges
+                 ;; of the staff lines appear wrongly in on-screen display
+                 ;; (and, to a lesser extent, in print) - they stick out a pixel.
+                 ;; The solution is to extend bar lines only to the middle
+                 ;; of the staff line - unless they have different colors,
+                 ;;when it would be undesirable.
+                 (set! staff-extent (ly:staff-symbol::height staff-symbol))
+                 (if (and (eq? bar-line-color staff-color)
+                          radius)
+                     (set! staff-extent
+                       (interval-scale staff-extent
+                                       (- 1 (* 1/2 (/ staff-line-thickness radius))))))))
+       staff-extent))
+
+(define (bar-line::bar-y-extent grob refpoint)
+  (let* ((extent (ly:grob-property grob 'bar-extent '(0 . 0)))
+         (rel-y (ly:grob-relative-coordinate grob refpoint Y))
+         (y-extent (coord-translate extent rel-y)))
+
+        y-extent))
+
+(define-public (ly:bar-line::print grob)
+  (let ((glyph (ly:grob-property grob 'glyph-name))
+        (extent (ly:grob-property grob 'bar-extent '(0 . 0))))
+
+       (if (and (not (eq? glyph '()))
+                (> (interval-length extent) 0))
+           (bar-line::compound-bar-line grob glyph extent #f)
+           #f)))
+
+(define-public (bar-line::compound-bar-line grob glyph extent rounded)
+  (let* ((line-thickness (layout-line-thickness grob))
+         (height (interval-length extent))
+         (kern (* (ly:grob-property grob 'kern 1) line-thickness))
+         (thinkern (* (ly:grob-property grob 'thin-kern 1) line-thickness))
+         (hair (* (ly:grob-property grob 'hair-thickness 1) line-thickness))
+         (fatline (* (ly:grob-property grob 'thick-thickness 1) line-thickness))
+         (thin-stil (make-simple-bar-line grob hair extent rounded))
+         (thick-stil (make-simple-bar-line grob fatline extent rounded))
+         (colon-stil (make-colon-bar-line grob))
+         (glyph (cond
+                  ((not glyph) "")
+                  ((string=? glyph "||:") "|:")
+                  ;; bar-line::compound-bar-line is called only if
+                  ;; height > 0, but just in case ...
+                  ((and (string=? glyph ":|")
+                        (zero? height)) "|.")
+                  ((and (string=? glyph "|:")
+                        (zero? height)) ".|")
+                  (else glyph)))
+         (stencil (cond
+                    ((string=? glyph "|") thin-stil)
+                    ((string=? glyph ".") thick-stil)
+                    ((string=? glyph "||")
+                     (ly:stencil-combine-at-edge
+                       (ly:stencil-combine-at-edge
+                         '() X LEFT thin-stil thinkern)
+                       X RIGHT thin-stil thinkern))
+                    ((string=? glyph "|.")
+                     (ly:stencil-combine-at-edge
+                       thick-stil X LEFT thin-stil kern))
+                    ((string=? glyph ".|")
+                     (ly:stencil-combine-at-edge
+                       thick-stil X RIGHT thin-stil kern))
+                    ((string=? glyph "|:")
+                     (ly:stencil-combine-at-edge
+                       (ly:stencil-combine-at-edge
+                         thick-stil X RIGHT thin-stil kern)
+                       X RIGHT colon-stil kern))
+                    ((string=? glyph ":|")
+                     (ly:stencil-combine-at-edge
+                       (ly:stencil-combine-at-edge
+                         thick-stil X LEFT thin-stil kern)
+                       X LEFT colon-stil kern))
+                    ((string=? glyph ":|:")
+                     (ly:stencil-combine-at-edge
+                       (ly:stencil-combine-at-edge
+                         (ly:stencil-combine-at-edge
+                           (ly:stencil-combine-at-edge
+                             '() X LEFT thick-stil thinkern)
+                           X LEFT colon-stil kern)
+                         X RIGHT thick-stil kern)
+                       X RIGHT colon-stil kern))
+                    ((string=? glyph ":|.|:")
+                     (ly:stencil-combine-at-edge
+                       (ly:stencil-combine-at-edge
+                         (ly:stencil-combine-at-edge
+                           (ly:stencil-combine-at-edge
+                             thick-stil X LEFT thin-stil kern)
+                           X LEFT colon-stil kern)
+                         X RIGHT thin-stil kern)
+                       X RIGHT colon-stil kern))
+                    ((string=? glyph ":|.:")
+                     (ly:stencil-combine-at-edge
+                       (ly:stencil-combine-at-edge
+                         (ly:stencil-combine-at-edge
+                           thick-stil X LEFT thin-stil kern)
+                         X LEFT colon-stil kern)
+                       X RIGHT colon-stil kern))
+                    ((string=? glyph ".|.")
+                     (ly:stencil-combine-at-edge
+                       (ly:stencil-combine-at-edge
+                         '() X LEFT thick-stil thinkern)
+                       X RIGHT thick-stil kern))
+                    ((string=? glyph "|.|")
+                     (ly:stencil-combine-at-edge
+                       (ly:stencil-combine-at-edge
+                         thick-stil X LEFT thin-stil kern)
+                       X RIGHT thin-stil kern))
+                    ((string=? glyph ":")
+                     (make-dotted-bar-line grob extent))
+                    ((or (string=? glyph "|._.|")
+                         (string-contains glyph "S"))
+                     (make-segno-bar-line grob glyph extent rounded))
+                    ((string=? glyph "'")
+                     (make-tick-bar-line grob (interval-end extent) rounded))
+                    ((string=? glyph "dashed")
+                     (make-dashed-bar-line grob extent hair))
+                    ((string=? glyph "kievan")
+                     (make-kievan-bar-line grob))
+                    (else (make-empty-bar-line grob extent)))))
+         stencil))
+
+(define-public (ly:bar-line::calc-anchor grob)
+  (let* ((line-thickness (layout-line-thickness grob))
+         (kern (* (ly:grob-property grob 'kern 1) line-thickness))
+         (glyph (ly:grob-property grob 'glyph-name ""))
+         (x-extent (ly:grob-extent grob grob X))
+         (dot-width (+ (interval-length
+                         (ly:stencil-extent
+                           (ly:font-get-glyph
+                             (ly:grob-default-font grob)
+                             "dots.dot")
+                           X))
+                       kern))
+         (anchor 0.0))
+
+        (if (> (interval-length x-extent) 0)
+            (begin
+              (set! anchor (interval-center x-extent))
+              (cond ((string=? glyph "|:")
+                     (set! anchor (+ anchor (/ dot-width -2.0))))
+                    ((string=? glyph ":|")
+                     (set! anchor (+ anchor (/ dot-width 2.0)))))))
+        anchor))
+
+(define-public (bar-line::calc-glyph-name grob)
+  (let* ((glyph (ly:grob-property grob 'glyph))
+         (dir (ly:item-break-dir grob))
+         (result (assoc-get glyph bar-glyph-alist))
+         (glyph-name (if (= dir CENTER)
+                         glyph
+                         (if (and result
+                                  (string? (index-cell result dir)))
+                            (index-cell result dir)
+                            #f))))
+        glyph-name))
+
+(define-public (bar-line::calc-break-visibility grob)
+  (let* ((glyph (ly:grob-property grob 'glyph))
+         (result (assoc-get glyph bar-glyph-alist)))
+
+    (if result
+        (vector (string? (car result)) #t (string? (cdr result)))
+        all-invisible)))
+
+;; which span bar belongs to a bar line?
+
+(define-public span-bar-glyph-alist
+  '(("|:" . ".|")
+    ("||:" . ".|")
+    (":|" . "|.")
+    (":|.:" . "|.")
+    (":|:" . ".|.")
+    (":|.|:" . "|.|")
+    (":|.|" . "|.")
+    ("S" . "||" )
+    ("S|" . "||")
+    ("|S" . "||")
+    ("S|:" . ".|")
+    (".S|:" . ".|")
+    (":|S" . "|.")
+    (":|S." . "|.")
+    (":|S|:" . "|._.|")
+    (":|S.|:" . "|._.|")
+    ("kievan" . "")
+    ("'" . "")))
+
+;; span bar callbacks
+
+(define-public (ly:span-bar::calc-glyph-name grob)
+  (let* ((elts (ly:grob-object grob 'elements))
+         (pos (1- (ly:grob-array-length elts)))
+         (glyph '()))
+
+        (while (and (eq? glyph '())
+                    (> pos -1))
+               (begin (set! glyph (ly:grob-property (ly:grob-array-ref elts pos)
+                                                    'glyph-name))
+                      (set! pos (1- pos))))
+         (if (eq? glyph '())
+             (begin (ly:grob-suicide! grob)
+                    (set! glyph "")))
+        (assoc-get glyph span-bar-glyph-alist glyph)))
+
+(define-public (ly:span-bar::width grob)
+  (let ((width (cons 0 0)))
+
+       (if (grob::is-live? grob)
+           (let* ((glyph (ly:grob-property grob 'glyph-name))
+                  (stencil (bar-line::compound-bar-line grob glyph (cons -1 1) #f)))
+
+                 (set! width (ly:stencil-extent stencil X))))
+       width))
+
+(define-public (ly:span-bar::before-line-breaking grob)
+  (let ((elts (ly:grob-object grob 'elements)))
+
+       (if (zero? (ly:grob-array-length elts))
+           (ly:grob-suicide! grob))))
+
+;; The method used in the following routine depends on bar_engraver
+;; not being removed from staff context.  If bar_engraver is removed,
+;; the size of the staff lines is evaluated as 0, which results in a
+;; solid span bar line with faulty y coordinate.
+;;
+;; This routine was originally by Juergen Reuter, but it was a on the
+;; bulky side. Rewritten by Han-Wen. Ported from c++ to Scheme by Marc Hohl.
+(define-public (ly:span-bar::print grob)
+  (let* ((elts-array (ly:grob-object grob 'elements))
+         (refp (ly:grob-common-refpoint-of-array grob elts-array Y))
+         (elts (reverse (sort (ly:grob-array->list elts-array)
+                              ly:grob-vertical<?)))
+         ;; Elements must be ordered according to their y coordinates
+         ;; relative to their common axis group parent.
+         ;; Otherwise, the computation goes mad.
+         (glyph (ly:grob-property grob 'glyph-name))
+         (span-bar empty-stencil))
+
+        (if (string? glyph)
+            (let* ((extents '())
+                   (make-span-bars '())
+                   (model-bar #f))
+
+                  ;; we compute the extents of each system and store them
+                  ;; in a list; dito for the 'allow-span-bar property.
+                  ;; model-bar takes the bar grob, if given.
+                  (map (lambda (bar)
+                       (let* ((ext (bar-line::bar-y-extent bar refp))
+                              (staff-symbol (ly:grob-object bar 'staff-symbol)))
+
+                             (if (ly:grob? staff-symbol)
+                                 (let ((refp-extent (ly:grob-extent staff-symbol refp Y)))
+
+                                      (set! ext (interval-union ext refp-extent))
+
+                                      (if (> (interval-length ext) 0)
+                                          (begin
+                                            (set! extents (append extents (list ext)))
+                                            (set! model-bar bar)
+                                            (set! make-span-bars
+                                              (append make-span-bars
+                                                      (list (ly:grob-property bar 'allow-span-bar #t))))))))))
+                       elts)
+                  ;; if there is no bar grob, we use the callback argument
+                  (if (not model-bar)
+                      (set! model-bar grob))
+                  ;; we discard the first entry in make-span-bars, because its corresponding
+                  ;; bar line is the uppermost and therefore not connected to another bar line
+                  (if (pair? make-span-bars)
+                      (set! make-span-bars (cdr make-span-bars)))
+                  ;; the span bar reaches from the lower end of the upper staff
+                  ;; to the upper end of the lower staff - when allow-span-bar is #t
+                  (reduce (lambda (curr prev)
+                                  (let ((l (cons 0 0))
+                                        (allow-span-bar (car make-span-bars)))
+
+                                       (set! make-span-bars (cdr make-span-bars))
+                                       (if (> (interval-length prev) 0)
+                                           (begin
+                                             (set! l (cons (cdr prev) (car curr)))
+                                             (if (or (zero? (interval-length l))
+                                                     (not allow-span-bar))
+                                                 (begin
+                                                   ;; there is overlap between the bar lines
+                                                   ;; or 'allow-span-bar = #f.
+                                                   ;; Do nothing.
+                                                 )
+                                                 (set! span-bar
+                                                       (ly:stencil-add span-bar
+                                                                       (bar-line::compound-bar-line
+                                                                         model-bar
+                                                                         glyph
+                                                                         l
+                                                                         #f))))))
+                                       curr))
+                          "" extents)
+                  (set! span-bar (ly:stencil-translate-axis
+                                   span-bar
+                                   (- (ly:grob-relative-coordinate grob refp Y))
+                                   Y))))
+        span-bar))
index 5ce96901678af7dd69a26ecbc990aeb8daa09d58..8d9c457037538c4bddd95e8d44ecaad4ee1c6105 100644 (file)
@@ -36,6 +36,50 @@ note)."
  "The line between note heads for a pitch range."
  '(gap note-heads thickness))
 
+(ly:add-interface
+ 'bar-line-interface
+ "Print a special bar symbol.  It replaces the regular bar
+symbol with a special symbol.  The argument @var{bartype}
+is a string which specifies the kind of bar line to print.
+Options are @code{|}, @code{:|}, @code{|:}, @code{:|:}, @code{:|.|:},
+@code{:|.:}, @code{.}, @code{||}, @code{|.}, @code{.|}, @code{.|.},
+@code{|.|}, @code{:}, @code{dashed}, @code{'} and @code{S}.
+
+These produce, respectively, a normal bar line, a right repeat, a left repeat,
+a thick double repeat, a thin-thick-thin double repeat,
+a thin-thick double repeat, a thick bar, a double bar, a start bar,
+an end bar, a thick double bar, a thin-thick-thin bar,
+a dotted bar, a dashed bar, a tick as bar line and a segno bar.
+
+In addition, there is an option
+@code{||:} which is equivalent to @code{|:} except at line
+breaks, where it produces a double bar (@code{||}) at the
+end of the line and a repeat sign (@code{|:}) at the
+beginning of the new line.
+
+For segno, @code{S} produces a segno sign except at line breaks,
+where it produces a double bar (@code{||}) at the
+end of the line and a segno sign at the beginning of the new line.
+@code{|S} is equivalent to @code{S} but produces a simple bar line
+(@code{|}) instead of a double bar line (@code{||}) at line breaks.
+@code{S|} produces the segno sign at line breaks and starts the following
+line without special bar lines.
+
+@code{S|:} and @code{:|S} are used for repeat/segno combinations that are
+separated at line breaks.  Alternatively, @code{.S|:} and @code{:|S.}
+may be used which combine repeat signs and segno at the same line in
+case of a line break.  @code{:|S|:} is a combination of a left repeat
+(@code{:|}), a segno (@code{S}) and a right repeat @code{|:} which
+splits before the segno at line breaks; @code{:|S.|:} splits after
+the segno sign.
+
+If @var{bartype} is set to @code{empty} then nothing is
+printed, but a line break is allowed at that spot.
+
+@code{gap} is used for the gaps in dashed bar lines."
+ '(allow-span-bar bar-extent gap glyph glyph-name has-span-bar
+   hair-thickness kern thin-kern thick-thickness))
+
 (ly:add-interface
  'bass-figure-interface
  "A bass figure text."
@@ -212,6 +256,14 @@ interesting enough to maintain a hara-kiri staff."
  "Supports setting of spacing variables."
  '(spacing-increment shortest-duration-space))
 
+(ly:add-interface
+ 'span-bar-interface
+ "A bar line that is spanned between other barlines.
+  This interface is used for bar lines that connect different
+  staves."
+ '(glyph-name elements pure-Y-common pure-relevant-grobs
+   pure-relevant-items pure-relevant-spanners))
+
 (ly:add-interface
  'stanza-number-interface
  "A stanza number, to be put in from of a lyrics line."
index 91ece1e476a360785b81614f636d59e79d9123d7..ec1097a32b7ace1ae756e86f61fd5fa08f6cffd7 100644 (file)
@@ -652,6 +652,10 @@ right (@var{dir}=+1)."
 (define (other-axis a)
   (remainder (+ a 1) 2))
 
+(define-public (interval-scale iv factor)
+  (cons (* (car iv) factor)
+    (* (cdr iv) factor)))
+
 (define-public (interval-widen iv amount)
   (cons (- (car iv) amount)
     (+ (cdr iv) amount)))
index 190670045cd912be3972785fd3d16bdf31370c7b..5a6b5f388dd2b52b456e4d1679da61def9d48fa7 100644 (file)
@@ -408,6 +408,7 @@ messages into errors.")
     "font.scm"
     "encoding.scm"
 
+    "bar-line.scm"
     "flag-styles.scm"
     "fret-diagrams.scm"
     "tablature.scm"
index 01e429cd195594cae2e3fcd202f3148bffdc7364..af55cc8fde11557f70c010b2f827e073278275e8 100644 (file)
@@ -358,68 +358,8 @@ and duration-log @var{log}."
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Bar lines.
+;; neighbor-interface routines
 
-;;
-;; How should a  bar line behave at a break?
-(define bar-glyph-alist
-  '((":|:" . (":|" . "|:"))
-    (":|.|:" . (":|" . "|:"))
-    (":|.:" . (":|" . "|:"))
-    ("||:" . ("||" . "|:"))
-    ("dashed" . ("dashed" . '()))
-    ("|" . ("|" . ()))
-    ("|s" . (() . "|"))
-    ("|:" . ("|" . "|:"))
-    ("|." . ("|." . ()))
-
-    ;; hmm... should we end with a bar line here?
-    (".|" . ("|" . ".|"))
-    (":|" . (":|" . ()))
-    ("||" . ("||" . ()))
-    (".|." . (".|." . ()))
-    ("|.|" . ("|.|" . ()))
-    ("" . ("" . ""))
-    (":" . (":" . ""))
-    ("." . ("." . ()))
-    ("'" . ("'" . ()))
-    ("empty" . (() . ()))
-    ("brace" . (() . "brace"))
-    ("bracket" . (() . "bracket"))
-
-    ;; segno bar lines
-    ("S" . ("||" . "S"))
-    ("|S" . ("|" . "S"))
-    ("S|" . ("S" . ()))
-    (":|S" . (":|" . "S"))
-    (":|S." . (":|S" . ()))
-    ("S|:" . ("S" . "|:"))
-    (".S|:" . ("|" . "S|:"))
-    (":|S|:" . (":|" . "S|:"))
-    (":|S.|:" . (":|S" . "|:"))
-
-    ;; ancient bar lines
-    ("kievan" . ("kievan" . ""))))
-
-(define-public (bar-line::calc-glyph-name grob)
-  (let* ((glyph (ly:grob-property grob 'glyph))
-        (dir (ly:item-break-dir grob))
-        (result (assoc-get glyph bar-glyph-alist))
-        (glyph-name (if (= dir CENTER)
-                        glyph
-                        (if (and result
-                                 (string? (index-cell result dir)))
-                            (index-cell result dir)
-                            #f))))
-    glyph-name))
-
-(define-public (bar-line::calc-break-visibility grob)
-  (let* ((glyph (ly:grob-property grob 'glyph))
-        (result (assoc-get glyph bar-glyph-alist)))
-
-    (if result
-       (vector (string? (car result)) #t (string? (cdr result)))
-       all-invisible)))
 
 (define-public (shift-right-at-line-begin g)
   "Shift an item to the right, but only at the start of the line."