]> git.donarmstrong.com Git - lilypond.git/commitdiff
Merge branch 'issue3330'
authorDavid Kastrup <dak@gnu.org>
Sun, 26 May 2013 00:35:05 +0000 (02:35 +0200)
committerDavid Kastrup <dak@gnu.org>
Sun, 26 May 2013 00:35:05 +0000 (02:35 +0200)
This merges a number of outstanding changes for

Issue 3330: bracketify-stencil moves grob's refpoint

comprising a rewrite of horizontal/vertical spacing.

27 files changed:
Documentation/de/notation/vocal.itely
Documentation/es/notation/vocal.itely
Documentation/fr/notation/vocal.itely
Documentation/ja/notation/vocal.itely
Documentation/notation/vocal.itely
Documentation/snippets/vertical-aligned-staffgroups-without-connecting-systemstartbar.ly
input/regression/fret-diagrams-size.ly
input/regression/markup-note-styles.ly
input/regression/markup-rest.ly
input/regression/markup-special-characters.ly
input/regression/page-headers-and-footers.ly
lily/box.cc
lily/constrained-breaking.cc
lily/dots.cc
lily/include/box.hh
lily/include/stencil.hh
lily/skyline.cc
lily/stencil-scheme.cc
lily/stencil.cc
ly/toc-init.ly
python/convertrules.py
scm/chord-name.scm
scm/define-markup-commands.scm
scm/markup.scm
scm/safe-lily.scm
scm/stencil.scm
scm/titling.scm

index 2a9bf9157a3e3cef809f334e6f19bd6c93ca5eeb..858db18da05c3557eb2a1002efa48a6ca3782aa1 100644 (file)
@@ -7,7 +7,7 @@
     Guide, node Updating translation committishes.
 @end ignore
 
-@c \version "2.17.18"
+@c \version "2.17.19"
 
 @c Translators: Till Paala
 
@@ -2064,7 +2064,7 @@ text = \lyricmode {
           "It has two lines."
         }
       }
-      \vspace #0.1 % adds vertical spacing between verses
+      \combine \null \vspace #0.1 % adds vertical spacing between verses
       \line { \bold "3."
         \column {
           "This is verse three."
@@ -2080,7 +2080,7 @@ text = \lyricmode {
           "It has two lines."
         }
       }
-      \vspace #0.1 % adds vertical spacing between verses
+      \combine \null \vspace #0.1 % adds vertical spacing between verses
       \line { \bold "5."
         \column {
           "This is verse five."
index 12b63fd7b09277d3b822392aba89f09ac09aab45..e48b69ea6da49c58812ce8f4d8c2e37d00ab2f12 100644 (file)
@@ -8,7 +8,7 @@
     Guide, node Updating translation committishes..
 @end ignore
 
-@c \version "2.17.18"
+@c \version "2.17.19"
 
 @node Música vocal
 @section Música vocal
@@ -2056,7 +2056,7 @@ text = \lyricmode {
           "It has two lines."
         }
       }
-      \vspace #0.1 % adds vertical spacing between verses
+      \combine \null \vspace #0.1 % adds vertical spacing between verses
       \line { \bold "3."
         \column {
           "This is verse three."
@@ -2072,7 +2072,7 @@ text = \lyricmode {
           "It has two lines."
         }
       }
-      \vspace #0.1 % adds vertical spacing between verses
+      \combine \null \vspace #0.1 % adds vertical spacing between verses
       \line { \bold "5."
         \column {
           "This is verse five."
index 1bea70ebdd126c683562957d9e0f1731a3650f8f..c5d18b9d565b0747a3ad54f897d721ba52e48841 100644 (file)
@@ -8,7 +8,7 @@
     Guide, node Updating translation committishes..
 @end ignore
 
-@c \version "2.17.18"
+@c \version "2.17.19"
 
 @c Translators: Valentin Villenave, Jean-Charles Malahieude
 @c Translation checkers: Jean-Jacques Gerbaud
@@ -2065,7 +2065,7 @@ text = \lyricmode {
           "Je me suis fait sécher..."
         }
       }
-      \vspace #0.1 % ajout d'espace vertical entre les couplets
+      \combine \null \vspace #0.1 % ajout d'espace vertical entre les couplets
       \line { \bold "3."
         \column {
           "Chante, rossignol, chante,"
@@ -2081,7 +2081,7 @@ text = \lyricmode {
           "Sans l'avoir mérité..."
         }
       }
-      \vspace #0.1 % ajout d'espace vertical entre les couplets
+      \combine \null \vspace #0.1 % ajout d'espace vertical entre les couplets
       \line { \bold "5."
         \column {
           "Je voudrais que la rose"
index 884b10e50f7a06c163cf7cef7ab86ae533b01798..dff6c23f670ac84a96904487355dd667a787fb69 100644 (file)
@@ -8,7 +8,7 @@
     Guide, node Updating translation committishes..
 @end ignore
 
-@c \version "2.17.18"
+@c \version "2.17.19"
 
 @c Translators: Yoshiki Sawada
 @c Translation status: post-GDP
@@ -2025,7 +2025,7 @@ text = \lyricmode {
           "It has two lines."
         }
       }
-      \vspace #0.1 % 次の歌詞との間に垂直方向のスペースを入れます
+      \combine \null \vspace #0.1 % 次の歌詞との間に垂直方向のスペースを入れます
       \line { \bold "3."
         \column {
           "This is verse three."
@@ -2041,7 +2041,7 @@ text = \lyricmode {
           "It has two lines."
         }
       }
-      \vspace #0.1 % 次の歌詞との間に垂直方向のスペースを入れます
+      \combine \null \vspace #0.1 % 次の歌詞との間に垂直方向のスペースを入れます
       \line { \bold "5."
         \column {
           "This is verse five."
index 54a656959183fa54feaadf145adb0b7c11bb0c2d..3d082ce8293da5e1d0e8c79097f905fd78928ec8 100644 (file)
@@ -7,7 +7,7 @@
     Guide, node Updating translation committishes..
 @end ignore
 
-@c \version "2.17.18"
+@c \version "2.17.19"
 
 @node Vocal music
 @section Vocal music
@@ -2009,7 +2009,7 @@ text = \lyricmode {
           "It has two lines."
         }
       }
-      \vspace #0.1 % adds vertical spacing between verses
+      \combine \null \vspace #0.1 % adds vertical spacing between verses
       \line { \bold "3."
         \column {
           "This is verse three."
@@ -2025,7 +2025,7 @@ text = \lyricmode {
           "It has two lines."
         }
       }
-      \vspace #0.1 % adds vertical spacing between verses
+      \combine \null \vspace #0.1 % adds vertical spacing between verses
       \line { \bold "5."
         \column {
           "This is verse five."
index 488eaef84c8fad7f6264d20931eee413480d9060..ca6a3ac017c8d5f4a5cf11912a1d2ab2be66c24c 100644 (file)
@@ -4,7 +4,7 @@
 %% and then run scripts/auxiliar/makelsr.py
 %%
 %% This file is in the public domain.
-\version "2.17.15"
+\version "2.17.19"
 
 \header {
   lsrtags = "paper-and-layout, staff-notation, syntax-and-expressions"
@@ -338,7 +338,7 @@ chromaticBach =
         \header {
                 title = \markup
                            \column {
-                             \vspace #1
+                             \combine \null \vspace #1
                              "Exercise: Improve the given choral"
                              " "
                             }
index 95942f78e5d13cfda057618c0ef8d8846dd25765..1dce8a9f4592213004f4609c5bb79538949488a3 100644 (file)
@@ -19,8 +19,6 @@ myFretDiagram =
 
 \markup \override #'(fret-diagram-details . ((finger-code . below-string))) {
   \myFretDiagram
-  \hspace #4
   \override #'(size . 1.5) \myFretDiagram
-  \hspace #8
   \override #'(size . 3) \myFretDiagram
 }
index c24c6d43b7d3d41c474313c6a6a868e7731845c2..224eaf69d0886fbdc3415874fc4227004ecdc690 100644 (file)
@@ -1,4 +1,4 @@
-\version "2.17.12"
+\version "2.17.19"
 
 \header {
   texidoc = "@code{\\note-by-number} and @code{\\note} support
@@ -37,7 +37,7 @@ all note head styles and straight flags."
 
 \markup {
   \column {
-    \vspace #1
+    \combine \null \vspace #1
     \underline "Note-head-styles:"
     \override #'(baseline-skip . 6)
     \show-note-styles #styles-list
@@ -46,7 +46,7 @@ all note head styles and straight flags."
 
 \markup {
   \column {
-    \vspace #1
+    \combine \null \vspace #1
     \underline "Modern-straight-flag:"
     \override #'(flag-style . modern-straight-flag)
     \show-note-styles #'(default)
@@ -55,7 +55,7 @@ all note head styles and straight flags."
 
 \markup {
   \column {
-    \vspace #1
+    \combine \null \vspace #1
     \underline "Old-straight-flag:"
     \override #'(flag-style . old-straight-flag)
     \show-note-styles #'(default)
index 593a3ea276262311b77f83b97e98d2ef3504645f..3c4895df9df883065bee7578c21eedbbd35f275e 100644 (file)
@@ -1,4 +1,4 @@
-\version "2.17.9"
+\version "2.17.19"
 
 \header {
   texidoc = "The rest markup function works for a variety of style, dot and
@@ -81,10 +81,10 @@ showMultiMeasureRests =
            semipetrucci
            kievan)))))
 
-\markup \column { \bold "Simple Rests" \vspace #0.1 }
+\markup \column { \bold "Simple Rests" \combine \null \vspace #0.1 }
 
 \showSimpleRest #"."
 
-\markup \column { \vspace #0.1 \bold "MultiMeasureRests" \vspace #0.1 }
+\markup \column { \combine \null \vspace #0.1 \bold "MultiMeasureRests" \combine \null \vspace #0.1 }
 
 \showMultiMeasureRests
index 8d3f2ce58f3c94b68e80a4f42f5e9df89e161852..b65a6f728eb8646e1ae5939b1d3eb666d3618ce6 100644 (file)
@@ -1,4 +1,4 @@
-\version "2.16.0"
+\version "2.17.19"
 \header {
   texidoc = "
   A list of special character ASCII aliases can be easily included.
@@ -21,7 +21,7 @@
   \italic \justify {
     &numero;2 &ndash; &OE;dipe&hellip;
   }
-  \vspace #0.5
+  \combine \null \vspace #0.5
   \bold "Lyric example:"
 }
 \new Lyrics \lyricmode {
index edec830b0e45d4a1d691bad8b9748ad1c08a609d..f50c73c8221451232b3387191805e45cf5a6da1f 100644 (file)
@@ -11,7 +11,7 @@
   ragged-last-bottom = ##f
 
   oddHeaderMarkup = \markup  {
-    \override #'(baseline-skip . 1)
+    \override #'(baseline-skip . 2.5)
     \center-column {
       \box \fill-line { \teeny " " " " }
       \on-the-fly #first-page "first-page-header-text"
@@ -24,7 +24,7 @@
   evenHeaderMarkup = \oddHeaderMarkup
 
   oddFooterMarkup = \markup \fill-line {
-    \override #'(baseline-skip . 0.5)
+    \override #'(baseline-skip . 1)
     \center-column {
        \on-the-fly #first-page "first-page-footer-text"
        \on-the-fly #last-page "last-page-footer-text"
index bc0a975ed0d3d91b0be837f5810af3fb8b991795..df5ccb75b2649c2e547b976b129ba78cbc5aee0a 100644 (file)
@@ -23,7 +23,8 @@ void
 Box::translate (Offset o)
 {
   for (Axis i = X_AXIS; i < NO_AXES; incr (i))
-    interval_a_[i] += o[i];
+    if (!is_empty (i))
+      interval_a_[i] += o[i];
 }
 
 void
@@ -54,8 +55,16 @@ Box::set_empty ()
 bool
 Box::is_empty () const
 {
-  return interval_a_[X_AXIS].is_empty ()
-         || interval_a_[Y_AXIS].is_empty ();
+  return is_empty (X_AXIS) && is_empty (Y_AXIS);
+}
+
+bool
+Box::is_empty (Axis a) const
+{
+  Interval empty;
+  empty.set_empty ();
+  return interval_a_[a][LEFT] == empty[LEFT]
+    && interval_a_[a][RIGHT] == empty[RIGHT];
 }
 
 Box::Box (Interval ix, Interval iy)
index 8d3b6967e42a05f37e308e6926a3d532b6c729b7..f8d4b0f5b2280d10ca669a1cb1678b3bdd5dc7ab 100644 (file)
@@ -572,7 +572,7 @@ Line_details::Line_details (Prob *pb, Output_def *paper)
   last_column_ = 0;
   force_ = 0;
   Stencil *st = unsmob_stencil (pb->get_property ("stencil"));
-  Interval stencil_extent = st->is_empty () ? Interval (0, 0)
+  Interval stencil_extent = st->is_empty (Y_AXIS) ? Interval (0, 0)
     : st->extent (Y_AXIS);
   shape_ = Line_shape (stencil_extent, stencil_extent); // pretend it goes all the way across
   tallness_ = 0;
index 43c47b77199a4576a7de3890f8011d485e925e84..20503ca5ae4bfc414a3af60abf7190d6ec985f34 100644 (file)
@@ -62,7 +62,6 @@ Dots::print (SCM d)
 
       for (int i = scm_to_int (c); i--;)
         {
-          d.translate_axis (2 * dw, X_AXIS);
           mol.add_at_edge (X_AXIS, RIGHT, d, dw);
         }
     }
index 63224f2f880debeb58567524dfb7dac51e1ae6a4..b0f899431188bf4d653ac448afbb6e074efdd6fa 100644 (file)
@@ -22,6 +22,7 @@ public:
   Interval &operator [] (Axis a);
   Real area () const;
   bool is_empty () const;
+  bool is_empty (Axis a) const;
 
   Offset center () const;
 
index 65c0b7a0f1e295e0523b3f035c4b7ad8fa8bdd30..6a89e022daba721fe449b708bb5867616c21ccfa 100644 (file)
@@ -71,6 +71,7 @@ public:
      Set dimensions to empty, or to (Interval (0, 0), Interval (0, 0) */
   void set_empty (bool);
   void add_at_edge (Axis a, Direction d, const Stencil &m, Real padding);
+  void stack (Axis a, Direction d, const Stencil &m, Real padding, Real mindist);
   void add_stencil (Stencil const &m);
   void translate (Offset);
   Stencil translated (Offset) const;
@@ -84,6 +85,7 @@ public:
   Interval extent (Axis) const;
   Box extent_box () const;
   bool is_empty () const;
+  bool is_empty (Axis) const;
   Stencil in_color (Real r, Real g, Real b) const;
   static SCM skylines_from_stencil (SCM, Real, Axis);
 };
index 31f4c5a1841a9547f2f196dcae2abe17f2132594..5073e69e14b3eaccb805a712e8979be7d9b8856f 100644 (file)
@@ -486,7 +486,8 @@ Skyline::Skyline (vector<Box> const &boxes, Axis horizon_axis, Direction sky)
   sky_ = sky;
 
   for (vsize i = 0; i < boxes.size (); i++)
-    if (!boxes[i].is_empty ())
+    if (!boxes[i].is_empty (X_AXIS)
+        && !boxes[i].is_empty (Y_AXIS))
       buildings.push_front (Building (boxes[i], horizon_axis, sky));
 
   buildings_ = internal_build_skyline (&buildings);
@@ -553,9 +554,12 @@ Skyline::Skyline (vector<Skyline_pair> const &skypairs, Direction sky)
 Skyline::Skyline (Box const &b, Axis horizon_axis, Direction sky)
 {
   sky_ = sky;
-  Building front (b, horizon_axis, sky);
-  single_skyline (front, &buildings_);
-  normalize ();
+  if (!b.is_empty (X_AXIS) && !b.is_empty (Y_AXIS))
+    {
+      Building front (b, horizon_axis, sky);
+      single_skyline (front, &buildings_);
+      normalize ();
+    }
 }
 
 void
@@ -593,7 +597,7 @@ Skyline::insert (Box const &b, Axis a)
     }
 
   /* do the same filtering as in Skyline (vector<Box> const&, etc.) */
-  if (b.is_empty ())
+  if (b.is_empty (X_AXIS) || b.is_empty (Y_AXIS))
     return;
 
   my_bld.splice (my_bld.begin (), buildings_);
index 37203f4edaed9cb817809c19ffbe598b2f60efe0..70358cd81e071af4e4034b021d1e11aca7c557a5 100644 (file)
@@ -84,12 +84,17 @@ LY_DEFINE (ly_stencil_extent, "ly:stencil-extent",
 }
 
 LY_DEFINE (ly_stencil_empty_p, "ly:stencil-empty?",
-           1, 0, 0, (SCM stil),
-           "Return whether @var{stil} is empty.")
+           1, 1, 0, (SCM stil, SCM axis),
+           "Return whether @var{stil} is empty.  If an optional"
+           " @var{axis} is supplied, the emptiness check is"
+           " restricted to that axis.")
 {
   Stencil *s = unsmob_stencil (stil);
   LY_ASSERT_SMOB (Stencil, stil, 1);
-  return scm_from_bool (s->is_empty ());
+  if (SCM_UNBNDP (axis))
+    return scm_from_bool (s->is_empty ());
+  LY_ASSERT_TYPE (is_axis, axis, 2);
+  return scm_from_bool (s->is_empty (Axis (scm_to_int (axis))));
 }
 
 LY_DEFINE (ly_stencil_combine_at_edge, "ly:stencil-combine-at-edge",
@@ -131,6 +136,57 @@ LY_DEFINE (ly_stencil_combine_at_edge, "ly:stencil-combine-at-edge",
   return result.smobbed_copy ();
 }
 
+LY_DEFINE (ly_stencil_stack, "ly:stencil-stack",
+           4, 2, 0, (SCM first, SCM axis, SCM direction,
+                     SCM second,
+                     SCM padding,
+                     SCM mindist),
+           "Construct a stencil by stacking @var{second} next to @var{first}."
+           "  @var{axis} can be 0 (x-axis) or@tie{}1 (y-axis)."
+           "  @var{direction} can be -1 (left or down) or@tie{}1 (right or"
+           " up).  The stencils are juxtaposed with @var{padding} as extra"
+           " space.  @var{first} and @var{second} may also be @code{'()} or"
+           " @code{#f}.  As opposed to @code{ly:stencil-combine-at-edge},"
+           " metrics are suited for successively accumulating lines of"
+           " stencils.  Also, @var{second} stencil is drawn last.\n\n"
+           "If @var{mindist} is specified, reference points are placed"
+           " apart at least by this distance.  If either of the stencils"
+           " is spacing, @var{padding} and @var{mindist} do not apply.")
+{
+  Stencil *s1 = unsmob_stencil (first);
+  Stencil *s2 = unsmob_stencil (second);
+  Stencil result;
+
+  SCM_ASSERT_TYPE (s1 || first == SCM_BOOL_F || first == SCM_EOL,
+                   first, SCM_ARG1, __FUNCTION__, "Stencil, #f or ()");
+  SCM_ASSERT_TYPE (s2 || second == SCM_BOOL_F || second == SCM_EOL,
+                   second, SCM_ARG4, __FUNCTION__, "Stencil, #f or ()");
+  LY_ASSERT_TYPE (is_axis, axis, 2);
+  LY_ASSERT_TYPE (is_direction, direction, 3);
+
+  Real p = 0.0;
+  if (padding != SCM_UNDEFINED)
+    {
+      LY_ASSERT_TYPE (scm_is_number, padding, 5);
+      p = scm_to_double (padding);
+    }
+  Real d = -infinity_f;
+  if (!SCM_UNBNDP (mindist))
+    {
+      LY_ASSERT_TYPE (scm_is_number, mindist, 6);
+      d = scm_to_double (mindist);
+    }
+
+  if (s1)
+    result = *s1;
+
+  if (s2)
+    result.stack (Axis (scm_to_int (axis)),
+                  Direction (scm_to_int (direction)), *s2, p, d);
+
+  return result.smobbed_copy ();
+}
+
 LY_DEFINE (ly_stencil_add, "ly:stencil-add",
            0, 0, 1, (SCM args),
            "Combine stencils.  Takes any number of arguments.")
@@ -180,7 +236,7 @@ LY_DEFINE (ly_make_stencil, "ly:make-stencil",
            "@item\n"
            "The vertical and horizontal extents of the object, given as"
            " pairs.  If an extent is unspecified (or if you use"
-           " @code{(1000 . -1000)} as its value), it is taken to be empty.\n"
+           " @code{empty-interval} as its value), it is taken to be empty.\n"
            "@end enumerate\n")
 {
   SCM_ASSERT_TYPE (!scm_is_pair (expr)
index 0a7f40205d610ef16d331675657132752ecf0403..c8985105ea44f0216ca58a3153a31cb89f3b55f2 100644 (file)
@@ -66,13 +66,15 @@ Stencil::extent (Axis a) const
 
 bool
 Stencil::is_empty () const
-/* If only one of X- or Y-extent is empty; such a stencil can be useful
- * for backspacing, as with \hspace #-2, so we do not consider it empty.
- */
 {
   return (expr_ == SCM_EOL
-          || (dim_[X_AXIS].is_empty ()
-              && dim_[Y_AXIS].is_empty ()));
+          || dim_.is_empty ());
+}
+
+bool
+Stencil::is_empty (Axis a) const
+{
+  return dim_.is_empty (a);
 }
 
 SCM
@@ -176,9 +178,10 @@ Stencil::translate (Offset o)
       incr (a);
     }
 
-  expr_ = scm_list_n (ly_symbol2scm ("translate-stencil"),
-                      ly_offset2scm (o),
-                      expr_, SCM_UNDEFINED);
+  if (!scm_is_null (expr_))
+    expr_ = scm_list_n (ly_symbol2scm ("translate-stencil"),
+                        ly_offset2scm (o),
+                        expr_, SCM_UNDEFINED);
   if (!is_empty ())
     dim_.translate (o);
 }
@@ -206,7 +209,11 @@ void
 Stencil::add_stencil (Stencil const &s)
 {
   SCM cs = ly_symbol2scm ("combine-stencil");
-  if (scm_is_pair (expr_)
+  if (scm_is_null (expr_))
+    expr_ = s.expr_;
+  else if (scm_is_null (s.expr_))
+    ;
+  else if (scm_is_pair (expr_)
       && scm_is_eq (cs, scm_car (expr_)))
     {
       if (scm_is_pair (s.expr_)
@@ -244,7 +251,7 @@ Stencil::set_empty (bool e)
 void
 Stencil::align_to (Axis a, Real x)
 {
-  if (is_empty ())
+  if (is_empty (a))
     return;
 
   Interval i (extent (a));
@@ -252,28 +259,155 @@ Stencil::align_to (Axis a, Real x)
 }
 
 /*  See scheme Function.  */
+
+// Any stencil that is empty in the orthogonal axis is spacing.
+// Spacing is not subjected to the max (0) rule and can thus be
+// negative.
+
 void
 Stencil::add_at_edge (Axis a, Direction d, Stencil const &s, Real padding)
 {
-  Interval my_extent = dim_[a];
-  Interval i (s.extent (a));
-  Real his_extent;
-  if (i.is_empty ())
+  // Material that is empty in the axis of reference has only limited
+  // usefulness for combining.  We still retain as much information as
+  // available since there may be uses like setting page links or
+  // background color or watermarks, and off-axis extents.
+
+  if (is_empty (a))
     {
-      programming_error ("Stencil::add_at_edge: adding empty stencil.");
-      his_extent = 0.0;
+      add_stencil (s);
+      return;
     }
-  else
-    his_extent = i[-d];
 
-  Real offset = (my_extent.is_empty () ? 0.0 : my_extent[d] - his_extent)
-                + d * padding;
+  Interval first_extent = extent (a);
+
+  if (s.is_empty (a))
+    {
+      Stencil toadd (s);
+      // translation does not affect axis-empty extent box.
+      toadd.translate_axis (first_extent[d], a);
+      add_stencil (toadd);
+      return;
+    }
+
+  Interval next_extent = s.extent (a);
+
+  bool first_is_spacing = is_empty (other_axis (a));
+  bool next_is_spacing = s.is_empty (other_axis (a));
+
+  Real offset = first_extent[d] - next_extent[-d];
+
+  if (!(first_is_spacing || next_is_spacing))
+    {
+      offset += d * padding;
+    }
 
   Stencil toadd (s);
   toadd.translate_axis (offset, a);
   add_stencil (toadd);
 }
 
+// Stencil::stack is mainly used for assembling lines or columns
+// of stencils.  For the most common case of adding at the right, the
+// reference point of the added stencil is usually placed at the right
+// edge of the current one, unless the added stencil has a negative
+// left extent in which case its left edge is placed at the right edge
+// of the current one.
+//
+// Spacing is special in that it is applied without padding.  Spacing
+// at the right edge shifts the right edge accordingly.
+//
+// For spacing at the left edge, there are several approaches.  In
+// order to get to predictable behavior, we want to have at least a
+// continuous approach.  An obvious idea is to do a "translate" by the
+// appropriate amount.  Doing that while retaining the nominal left
+// edge seems like the most straightforward way.
+
+void
+Stencil::stack (Axis a, Direction d, Stencil const &s, Real padding, Real mindist)
+{
+  // Material that is empty in the axis of reference can't be sensibly
+  // stacked.  We just revert to add_at_edge behavior then.
+
+  if (is_empty (a))
+    {
+      Stencil toadd (s);
+      toadd.add_stencil (*this);
+      expr_ = toadd.expr ();
+      dim_ = toadd.extent_box ();
+      return;
+    }
+
+  Interval first_extent = extent (a);
+
+  if (s.is_empty (a))
+    {
+      Stencil toadd (s);
+      toadd.translate_axis (first_extent[d], a);
+      toadd.add_stencil (*this);
+      expr_ = toadd.expr ();
+      dim_ = toadd.extent_box ();
+      return;
+    }
+
+  Interval next_extent = s.extent (a);
+
+  // It is somewhat tedious to special-case all spacing, but it turns
+  // out that not doing so makes it astonishingly hard to make the
+  // code do the correct thing.
+
+  // If first is spacing, we translate second accordingly without
+  // letting this affect its backward edge.
+  if (is_empty (other_axis (a)))
+    {
+      Stencil toadd (s);
+      Real offset = d * first_extent.delta ();
+      toadd.translate_axis (offset, a);
+      toadd.add_stencil (*this);
+      expr_ = toadd.expr ();
+      dim_ = toadd.extent_box ();
+      dim_[a][-d] = next_extent[-d];
+      dim_[a][d] = next_extent[d] + offset;
+      return;
+    }
+
+  // If next is spacing, similar action:
+  if (s.is_empty (other_axis (a)))
+    {
+      Stencil toadd (s);
+      Real offset = first_extent [d];
+      toadd.translate_axis (offset, a);
+      toadd.add_stencil (*this);
+      expr_ = toadd.expr ();
+      dim_ = toadd.extent_box ();
+      dim_[a][-d] = first_extent[-d];
+      dim_[a][d] = first_extent[d] + d * next_extent.delta ();
+      return;
+    }
+
+
+  Real offset = first_extent[d];
+
+  // If the added stencil has a backwardly protruding edge, we make
+  // room for it when combining.
+
+  if (d * next_extent [-d] < 0)
+    offset -= next_extent [-d];
+
+  offset += d * padding;
+
+  if (offset * d < mindist)
+    offset = d * mindist;
+
+  Stencil toadd (s);
+  toadd.translate_axis (offset, a);
+  toadd.add_stencil (*this);
+  expr_ = toadd.expr ();
+  dim_ = toadd.extent_box ();
+  dim_[a][-d] = first_extent [-d];
+  dim_[a][d] = next_extent [d] + offset;
+}
+
+
 Stencil
 Stencil::in_color (Real r, Real g, Real b) const
 {
index 3a3f6e08ab1724f432285706c722792342b2dbee..32eeb462f8e77e0f3893058708334d68ddafc2b9 100644 (file)
@@ -25,7 +25,7 @@
 \paper {
   tocTitleMarkup = \markup \huge \column {
     \fill-line { \null "Table of Contents" \null }
-    \hspace #1
+    \null
   }
   tocItemMarkup = \markup \fill-line {
     \fromproperty #'toc:text \fromproperty #'toc:page
index 11cd1729fd509eb7f0ad5f0d7c8267ec5d2eefb1..aee0530e9c71e98297b468e33212b4126c88de42 100644 (file)
@@ -3560,6 +3560,27 @@ def conv(str):
     str = re.sub ('cueClefOctavationStyle',      'cueClefTranspositionStyle',      str)
     return str
 
+@rule((2, 17, 19), r"\column { \vspace #2 } -> \column { \combine \null \vspace #2 }")
+def conv(str):
+    def vspace_replace(m):
+
+# vspace now always adds space and does not, for example, change the
+# impact of either baselineskip or descenders on the line above.
+#
+# We can't simulate the old behavior in a simpler manner.  A command
+# of its own is not really warranted since this behavior combines
+# badly enough with other spacing considerations (like baselineskip
+# and descenders) as to make it not all that useful.  So this
+# conversion rule is here more for compatibility's sake rather than
+# preserving desirable behavior.
+
+        str = re.sub (r"(\\\\?)vspace(\s)", r"\1combine \1null \1vspace\2", m.group(0))
+        return str
+
+    str = re.sub (r"\\(?:left-|right-|center-|)column\s*\{" + brace_matcher (20) + r"\}",
+                  vspace_replace, str)
+    return str
+
 # Guidelines to write rules (please keep this at the end of this file)
 #
 # - keep at most one rule per version; if several conversions should be done,
index 9823d8a08b4e8ba6a5399b2c69c8bd58c216295b..606d8066605390934e4a065330aaea4c3e506f8e 100644 (file)
@@ -46,7 +46,7 @@
       (make-line-markup (list empty-markup))
       (conditional-kern-before
        (alteration->text-accidental-markup alteration)
-       (= alteration FLAT) 0.2)))
+       (= alteration FLAT) 0.094725)))
 
 (define (accidental->markup-italian alteration)
   "Return accidental markup for ALTERATION, for use after an italian chord root name."
@@ -54,7 +54,7 @@
       (make-hspace-markup 0.2)
       (make-line-markup
        (list
-        (make-hspace-markup (if (= alteration FLAT) 0.7 0.5))
+        (make-hspace-markup (if (= alteration FLAT) 0.57285385 0.5))
        (make-raise-markup 0.7 (alteration->text-accidental-markup alteration))
        (make-hspace-markup (if (= alteration SHARP) 0.2 0.1))
        ))))
index 96236f176952a3140af0d6d8847d87ddbe9f0921..ecbe876ffa6e1a88b8f91d53b391cb5141340c7b 100755 (executable)
 ;; utility functions
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(define-public empty-stencil (ly:make-stencil '() '(1 . -1) '(1 . -1)))
+(define-public empty-stencil (ly:make-stencil '()
+                                              empty-interval empty-interval))
 (define-public point-stencil (ly:make-stencil "" '(0 . 0) '(0 . 0)))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -692,7 +693,6 @@ Create a box of the same height as the space in the current font."
 (define-markup-command (hspace layout props amount)
   (number?)
   #:category align
-  #:properties ((word-space))
   "
 @cindex creating horizontal spaces in text
 
@@ -707,8 +707,7 @@ Create an invisible object taking up horizontal space @var{amount}.
   three
 }
 @end lilypond"
-  (let ((corrected-space (- amount word-space)))
-    (ly:make-stencil "" (cons 0 corrected-space) '(0 . 0))))
+  (ly:make-stencil "" (cons 0 amount) empty-interval))
 
 (define-markup-command (vspace layout props amount)
  (number?)
@@ -731,7 +730,7 @@ of @var{amount} multiplied by 3.
 }
 @end lilypond"
   (let ((amount (* amount 3.0)))
-    (ly:make-stencil "" (cons 0 0) (cons 0 amount))))
+    (ly:make-stencil "" empty-interval (cons 0 amount))))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1267,9 +1266,7 @@ determines the space between markups in @var{args}.
   (let ((stencils (interpret-markup-list layout props args)))
     (if (= text-direction LEFT)
         (set! stencils (reverse stencils)))
-    (stack-stencil-line
-     word-space
-     (remove ly:stencil-empty? stencils))))
+    (stack-stencil-line word-space stencils)))
 
 (define-markup-command (concat layout props args)
   (markup-list?)
@@ -1322,14 +1319,26 @@ equivalent to @code{\"fi\"}.
                     ;; justify only stretches lines.
                    (* 0.7 base-space)
                    base-space))
+  (define (stencil-space stencil line-start)
+    (if (ly:stencil-empty? stencil X)
+        0
+        (cdr (ly:stencil-extent
+              (ly:stencil-stack (if line-start
+                                    empty-stencil
+                                    point-stencil)
+                                X RIGHT stencil)
+              X))))
   (define (take-list width space stencils
                     accumulator accumulated-width)
     "Return (head-list . tail) pair, with head-list fitting into width"
     (if (null? stencils)
        (cons accumulator stencils)
        (let* ((first (car stencils))
-               (first-wid (cdr (ly:stencil-extent (car stencils) X)))
-               (newwid (+ space first-wid accumulated-width)))
+               (first-wid (stencil-space first (null? accumulator)))
+               (newwid (+ (if (or (ly:stencil-empty? first Y)
+                                  (ly:stencil-empty? first X))
+                              0 space)
+                          first-wid accumulated-width)))
          (if (or (null? accumulator)
                   (< newwid width))
               (take-list width space
@@ -1343,17 +1352,20 @@ equivalent to @code{\"fi\"}.
                                   '() 0.0))
           (line-stencils (car line-break))
           (space-left (- line-width
-                          (apply + (map (lambda (x) (cdr (ly:stencil-extent x X)))
-                                        line-stencils))))
+                          (stencil-space
+                           (stack-stencil-line 0 line-stencils)
+                           #t)))
+           (line-words (count (lambda (s) (not (or (ly:stencil-empty? s Y)
+                                                   (ly:stencil-empty? s X))))
+                              line-stencils))
           (line-word-space (cond ((not justify) space)
                                   ;; don't stretch last line of paragraph.
                                   ;; hmmm . bug - will overstretch the last line in some case.
                                   ((null? (cdr line-break))
                                    base-space)
-                                  ((null? line-stencils) 0.0)
-                                  ((null? (cdr line-stencils)) 0.0)
-                                  (else (/ space-left (1- (length line-stencils))))))
-          (line (stack-stencil-line line-word-space
+                                  ((< line-words 2) space)
+                                  (else (/ space-left (1- line-words)))))
+           (line (stack-stencil-line line-word-space
                                      (if (= text-dir RIGHT)
                                          (reverse line-stencils)
                                          line-stencils))))
@@ -1375,8 +1387,7 @@ equivalent to @code{\"fi\"}.
                (word-space)
                (text-direction RIGHT))
   "Internal markup list command used to define @code{\\justify} and @code{\\wordwrap}."
-  (wordwrap-stencils (remove ly:stencil-empty?
-                             (interpret-markup-list layout props args))
+  (wordwrap-stencils (interpret-markup-list layout props args)
                      justify
                      word-space
                      (or line-width
@@ -1446,10 +1457,9 @@ the line width, where @var{X} is the number of staff spaces.
                                para-strings))
          (para-lines (map (lambda (words)
                             (let* ((stencils
-                                    (remove ly:stencil-empty?
-                                            (map (lambda (x)
-                                                   (interpret-markup layout props x))
-                                                 words))))
+                                    (map (lambda (x)
+                                           (interpret-markup layout props x))
+                                         words)))
                               (wordwrap-stencils stencils
                                                  justify word-space
                                                  line-width text-direction)))
@@ -1627,8 +1637,7 @@ in @var{args}.
 }
 @end lilypond"
   (let ((arg-stencils (interpret-markup-list layout props args)))
-    (stack-lines -1 0.0 baseline-skip
-                 (remove ly:stencil-empty? arg-stencils))))
+    (stack-lines -1 0.0 baseline-skip arg-stencils)))
 
 (define-markup-command (dir-column layout props args)
   (markup-list?)
index 9253c378db998950de8cb4bdb3ee1a56f36575ee..45652c0a5c8c1a63b67ea4b0ca6b944c2dd747e9 100644 (file)
@@ -63,21 +63,11 @@ Example:
   (cons (acons key val (car chain)) (cdr chain)))
 
 (define-public (stack-stencil-line space stencils)
-  "Adjoin a list of STENCILS along the X axis, leaving SPACE between the
-   end of each stencil and the reference point of the following stencil."
-  (if (and (pair? stencils)
-           (ly:stencil? (car stencils)))
-
-      (if (and (pair? (cdr stencils))
-               (ly:stencil? (cadr stencils)))
-          (let* ((tail (stack-stencil-line space (cdr stencils)))
-                 (head (car stencils))
-                 (xoff (+ space (interval-end (ly:stencil-extent head X)))))
-            (ly:stencil-add head
-                            (ly:stencil-translate-axis tail xoff X)))
-          (car stencils))
-      (ly:make-stencil '() '(0 . 0) '(0 . 0))))
-
+  "Adjoin a list of @var{stencils} along the X axis, leaving
+@var{space} between the end of each stencil and the beginning of the
+following stencil.  Stencils with empty Y extent are not given
+@var{space} before them and don't avoid overlapping other stencils."
+  (stack-stencils X RIGHT space (filter ly:stencil? stencils)))
 
 ;;; convert a full markup object to an approximate pure string representation
 
index 202cad688375bf8dab64daf971a2abd0e661f295..cfc088c8b37dd6cd9d069452d66745e9c066094c 100644 (file)
    ly:stencil-combine-at-edge
    ly:stencil-expr
    ly:stencil-extent
+   ly:stencil-stack
    ly:stencil-translate
    ly:stencil-translate-axis
    ly:stencil?
index 678ba7c2e2d8912bd5bbe5a7c9945525ba6b8a8a..d7ba2e407901552fbaecd7327eba5b909cae0c10 100644 (file)
 (define-public (stack-stencils axis dir padding stils)
   "Stack stencils @var{stils} in direction @var{axis}, @var{dir}, using
 @var{padding}."
-  (cond
-   ((null? stils) empty-stencil)
-   ((null? (cdr stils)) (car stils))
-   (else (ly:stencil-combine-at-edge
-         (car stils) axis dir (stack-stencils axis dir padding (cdr stils))
-         padding))))
-
-(define-public (stack-stencils-padding-list axis dir padding stils)
+  (reduce
+   (lambda (next front)
+     (ly:stencil-stack front axis dir next padding))
+   empty-stencil
+   stils))
+
+(define-public (stack-stencils-padding-list axis dir paddings stils)
   "Stack stencils @var{stils} in direction @var{axis}, @var{dir}, using
-a list of @var{padding}."
-  (cond
-   ((null? stils) empty-stencil)
-   ((null? (cdr stils)) (car stils))
-   (else (ly:stencil-combine-at-edge
-         (car stils)
-         axis dir
-         (stack-stencils-padding-list axis dir (cdr padding) (cdr stils))
-         (car padding)))))
+a list of @var{paddings}."
+  (if (null? stils)
+      empty-stencil
+      (fold
+       (lambda (next padding front)
+         (ly:stencil-stack front axis dir next padding))
+       (car stils)
+       (cdr stils)
+       paddings)))
 
 (define-public (centered-stencil stencil)
   "Center stencil @var{stencil} in both the X and Y directions."
@@ -67,33 +66,20 @@ a list of @var{padding}."
 
 (define-public (stack-lines dir padding baseline stils)
   "Stack vertically with a baseline skip."
-  (define result empty-stencil)
-  (define last-y #f)
-  (do
-      ((last-stencil #f (car p))
-       (p stils (cdr p)))
-
-      ((null? p))
-
-    (if (number? last-y)
-       (begin
-         (let* ((dy (max (+ (* dir (interval-bound (ly:stencil-extent last-stencil Y) dir))
-                            padding
-                            (* (- dir) (interval-bound (ly:stencil-extent (car p) Y) (- dir))))
-                         baseline))
-                (y (+ last-y  (* dir dy))))
-
-
-
-           (set! result
-                 (ly:stencil-add result (ly:stencil-translate-axis (car p) y Y)))
-           (set! last-y y)))
-       (begin
-         (set! last-y 0)
-         (set! result (car p)))))
-
-  result)
-
+  (reduce-right
+   (lambda (next back) (ly:stencil-stack next Y dir back padding baseline))
+   empty-stencil
+   (map
+    (lambda (s)
+      ;; X-empty stencils may add vertical space.  A stencil that is
+      ;; merely Y-empty counts as horizontal spacing.  Since we want
+      ;; those to register as lines of their own (is this a good
+      ;; idea?), we make them a separately visible line.
+      (if (and (ly:stencil-empty? s Y)
+               (not (ly:stencil-empty? s X)))
+          (ly:make-stencil (ly:stencil-expr s) (ly:stencil-extent s X) '(0 . 0))
+          s))
+    stils)))
 
 (define-public (bracketify-stencil stil axis thick protrusion padding)
   "Add brackets around @var{stil}, producing a new stencil."
@@ -104,7 +90,7 @@ a list of @var{padding}."
     (set! stil
          (ly:stencil-combine-at-edge stil (other-axis axis) 1 rb padding))
     (set! stil
-         (ly:stencil-combine-at-edge lb (other-axis axis) 1 stil padding))
+         (ly:stencil-combine-at-edge stil (other-axis axis) -1 lb padding))
     stil))
 
 (define (make-parenthesis-stencil
@@ -180,7 +166,7 @@ the more angular the shape of the parenthesis."
              y-extent half-thickness (- width) angularity))
         (rp (make-parenthesis-stencil
              y-extent half-thickness width angularity)))
-    (set! stencil (ly:stencil-combine-at-edge lp X RIGHT stencil padding))
+    (set! stencil (ly:stencil-combine-at-edge stencil X LEFT lp padding))
     (set! stencil (ly:stencil-combine-at-edge stencil X RIGHT rp padding))
     stencil))
 
index b6c1e0583d1a3dd7fc39977df7e447a90faac538..7118fb1a06a91bba99ac4e5aae8b5718b8849eb1 100644 (file)
@@ -100,4 +100,4 @@ with `header:'."
 
     (if (markup? markup)
        (interpret-markup layout props markup)
-       (ly:make-stencil '() '(1 . -1) '(1 . -1)))))
+        empty-stencil)))