]> git.donarmstrong.com Git - lilypond.git/commitdiff
Imported Upstream version 2.19.48
authorDr. Tobias Quathamer <toddy@debian.org>
Thu, 22 Sep 2016 08:33:58 +0000 (10:33 +0200)
committerDr. Tobias Quathamer <toddy@debian.org>
Thu, 22 Sep 2016 08:33:58 +0000 (10:33 +0200)
37 files changed:
.gitfilelist
Documentation/contributor/programming-work.itexi
Documentation/snippets/new/using-marklines-in-a-frenched-score.ly [new file with mode: 0644]
Documentation/web/news-front.itexi
Documentation/web/news.itexi
VERSION
flower/include/offset.hh
flower/offset.cc
input/regression/remove-layer-symbol.ly [new file with mode: 0644]
input/regression/tablature-micro-tone.ly
lily/arpeggio.cc
lily/beam.cc
lily/bezier.cc
lily/fingering-column.cc
lily/grob.cc
lily/hara-kiri-group-spanner.cc
lily/include/bezier.hh
lily/include/grob.hh
lily/keep-alive-together-engraver.cc
lily/line-interface.cc
lily/lookup.cc
lily/side-position-interface.cc
lily/slur-configuration.cc
lily/slur-scoring.cc
lily/stencil-integral.cc
lily/stencil-scheme.cc
lily/stencil.cc
lily/tuplet-bracket.cc
ly/Welcome-to-LilyPond-MacOS.ly
ly/Welcome_to_LilyPond.ly
out/ChangeLog
out/RELEASE-COMMIT
po/lilypond.pot
scm/define-grob-properties.scm
scm/lily-library.scm
scm/output-ps.scm
scm/translation-functions.scm

index 633ca3ccc07e011f334f320129fb42ea6de01864..abcb24f56ad3880bb54beb4fd1fb2ef7e317761e 100644 (file)
@@ -2025,6 +2025,7 @@ Documentation/snippets/new/staff-headword.ly
 Documentation/snippets/new/subdividing-beams.ly
 Documentation/snippets/new/unfretted-headword.ly
 Documentation/snippets/new/user-defined-time-signatures.ly
+Documentation/snippets/new/using-marklines-in-a-frenched-score.ly
 Documentation/snippets/new/using-the-whiteout-property.ly
 Documentation/snippets/new/utf-8.ly
 Documentation/snippets/new/wind-headword.ly
@@ -3484,6 +3485,7 @@ input/regression/relative.ly
 input/regression/remove-empty-context-mod.ly
 input/regression/remove-empty-staves-auto-knee.ly
 input/regression/remove-empty-staves-with-rests.ly
+input/regression/remove-layer-symbol.ly
 input/regression/repeat-line-break.ly
 input/regression/repeat-percent-count-visibility.ly
 input/regression/repeat-percent-count.ly
index 8dc8d2755bccbb31416d1b89e7846dad9a9080f9..d13b68099c00bee6e6cdf177b4276577a4b06196 100644 (file)
@@ -1758,11 +1758,29 @@ Acknowledge functions are called in the order engravers are
 @code{\consist}-ed (the only exception is if you set
 @code{must-be-last} to @code{#t}).
 
-If useful things are to be done to the acknowledged grobs, this
-should be deferred until all the acknowledging has finished, i.e.,
-store the acknowledged grobs and process the information in a
-@code{process-acknowledged ()} or @code{stop-translation-timestep ()} 
-function.
+There will always be a call to @code{process-acknowledged ()} whenever
+grobs have been created, and @emph{reading} stuff from grobs should be
+delayed until then since other acknowledgers might @emph{write} stuff
+into a grob even after your acknowledger has been called.  So the basic
+workflow is to use the various acknowledgers to @emph{record} the grobs
+you are interested in and @emph{write} stuff into them (or do read/write
+stuff that more or less is accumulative and/or really unrelated to other
+engravers), and then use the @code{process-acknowledged ()} hook for
+processing (including @emph{reading}) the grobs you had recorded.
+
+You can create new grobs in @code{process-acknowledged ()}.  That will lead
+to a new cycle of @code{acknowledger ()} calls followed by a new cycle of
+@code{process-acknowledged ()} calls.
+
+Only when all those cycles are over is @code{stop-translator-timestep ()}
+called, and then creating grobs is no longer an option.  You can still
+@q{process} parts of the grob there (if that means just reading out
+properties and possibly setting context properties based on them) but
+@code{stop-translation-timestep ()} is a cleanup hook, and other engravers
+might have already cleaned up stuff you might have wanted to use.
+Creating grobs in there is not possible since engravers and other code may
+no longer be in a state where they could process them, possibly causing
+a crash.
 
 
 @node Engraver declaration/documentation
diff --git a/Documentation/snippets/new/using-marklines-in-a-frenched-score.ly b/Documentation/snippets/new/using-marklines-in-a-frenched-score.ly
new file mode 100644 (file)
index 0000000..0fdefc9
--- /dev/null
@@ -0,0 +1,97 @@
+\version "2.19.48"
+\header {
+  lsrtags = "contexts-and-engravers, staff-notation"
+  texidoc = "
+Using @{MarkLine} contexts (such as in
+@uref{http://lsr.di.unimi.it/LSR/Item?id=1010, LSR1010}) in a
+Frenched score can be problematic if all the staves between two
+@code{MarkLine}s are removed in one system. The
+@code{Keep_alive_together_engraver} can be used within each
+@code{StaffGroup} to keep the @code{MarkLine} alive only as long
+as the other staves in the group stay alive.
+"
+  doctitle = "Using marklines in a Frenched score"
+}
+bars = {
+  \tempo "Allegro" 4=120
+  s1*2
+  \repeat unfold 5 { \mark \default s1*2 }
+  \bar "||"
+  \tempo "Adagio" 4=40
+  s1*2
+  \repeat unfold 8 { \mark \default s1*2 }
+  \bar "|."
+}
+winds = \repeat unfold 120 { c''4 }
+trumpet = { \repeat unfold 8 g'2 R1*16 \repeat unfold 4 g'2 R1*8 }
+trombone = { \repeat unfold 4 c'1 R1*8 d'1 R1*17 }
+strings = \repeat unfold 240 { c''8 }
+
+#(set-global-staff-size 16)
+\paper {
+  systems-per-page = 5
+  ragged-last-bottom = ##f
+}
+
+\layout {
+  indent = 15\mm
+  short-indent = 5\mm
+  \context {
+    \name MarkLine
+    \type Engraver_group
+    \consists Output_property_engraver
+    \consists Axis_group_engraver
+    \consists Mark_engraver
+    \consists Metronome_mark_engraver
+    \override VerticalAxisGroup.remove-empty = ##t
+    \override VerticalAxisGroup.remove-layer = #'any
+    \override VerticalAxisGroup.staff-affinity = #DOWN
+    \override VerticalAxisGroup.nonstaff-relatedstaff-spacing.basic-distance = 1
+    keepAliveInterfaces = #'()
+  }
+  \context {
+    \Staff
+    \override VerticalAxisGroup.remove-empty = ##t
+    \override VerticalAxisGroup.remove-layer = ##f
+  }
+  \context {
+    \StaffGroup
+    \accepts MarkLine
+    \consists Keep_alive_together_engraver
+  }
+  \context {
+    \Score
+    \remove Mark_engraver
+    \remove Metronome_mark_engraver
+  }
+}
+
+\score {
+  <<
+    \new StaffGroup = "winds" \with {
+      instrumentName = "Winds"
+      shortInstrumentName = "Winds"
+    } <<
+      \new MarkLine \bars
+      \new Staff \winds
+    >>
+    \new StaffGroup = "brass" <<
+      \new MarkLine \bars
+      \new Staff = "trumpet" \with {
+        instrumentName = "Trumpet"
+        shortInstrumentName = "Tpt"
+      } \trumpet
+      \new Staff = "trombone" \with {
+        instrumentName = "Trombone"
+        shortInstrumentName = "Tbn"
+      } \trombone
+    >>
+    \new StaffGroup = "strings" \with {
+      instrumentName = "Strings"
+      shortInstrumentName = "Strings"
+    } <<
+      \new MarkLine \bars
+      \new Staff = "strings" { \strings }
+    >>
+  >>
+}
index 67ce189469cd06d890890fd946ce91dfceb42d71..d9a715518bac1898db74ce6cad20bbf566a486ec 100644 (file)
@@ -9,10 +9,10 @@
 @c used for news about the upcoming release; see CG 10.2
 
 @newsItem
-@subheading LilyPond 2.19.47 released  @emph{August 13, 2016}
+@subheading LilyPond 2.19.48 released  @emph{September 13, 2016}
 
 We are happy to announce the release of LilyPond
-2.19.47.  This release includes a number of enhancements, and contains some
+2.19.48.  This release includes a number of enhancements, and contains some
 work in progress.  You will have access to the very latest features, but
 some may be incomplete, and you may encounter bugs and crashes.  If you
 require a stable version of LilyPond, we recommend using the 2.18
index 32cd7bde51eb6aeb941687f77a97f743545171dd..990d92ceaa87d5f905d15fa7435a245528693fbb 100644 (file)
@@ -26,6 +26,18 @@ NOTE:
   * don't duplicate entries from news-front.itexi
 @end ignore
 
+@newsItem
+@subheading LilyPond 2.19.47 released  @emph{August 31, 2016}
+
+We are happy to announce the release of LilyPond
+2.19.47.  This release includes a number of enhancements, and contains some
+work in progress.  You will have access to the very latest features, but
+some may be incomplete, and you may encounter bugs and crashes.  If you
+require a stable version of LilyPond, we recommend using the 2.18
+version.
+
+@newsEnd
+
 @newsItem
 @subheading LilyPond 2.19.46 released  @emph{July 26, 2016}
 
diff --git a/VERSION b/VERSION
index 0c746e0c7bccbe265d8a73a2a2545da6f961fc71..5a26a8bd8e090f722f335c92a82819190a9573e7 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1,7 +1,7 @@
 PACKAGE_NAME=LilyPond
 MAJOR_VERSION=2
 MINOR_VERSION=19
-PATCH_LEVEL=47
+PATCH_LEVEL=48
 MY_PATCH_LEVEL=
 VERSION_STABLE=2.18.2
-VERSION_DEVEL=2.19.47
+VERSION_DEVEL=2.19.48
index 8f395398b75e2768d31f476737142502c3a7eedd..a8c5987801069b01790b545b4a12db4c70923bfc 100644 (file)
@@ -111,7 +111,6 @@ public:
   Offset direction () const;
   Offset swapped () const;
 
-  Real arg () const;
   Real angle_degrees () const;
   Real length () const;
   bool is_sane () const;
@@ -124,8 +123,7 @@ IMPLEMENT_ARITHMETIC_OPERATOR (Offset, -);
 IMPLEMENT_ARITHMETIC_OPERATOR (Offset, *);
 
 Offset complex_multiply (Offset, Offset);
-Offset complex_divide (Offset, Offset);
-Offset complex_exp (Offset);
+Offset offset_directed (Real);
 
 inline Offset
 Offset::operator *= (Offset z2)
index 7cb267748190bf372c91a4ae08c122df676144a0..db1654f2d3d517f0ef29b90a3d8750353f0a89d5 100644 (file)
@@ -46,44 +46,67 @@ complex_multiply (Offset z1, Offset z2)
   return z;
 }
 
-Offset
-complex_conjugate (Offset o)
-{
-  o[Y_AXIS] = -o[Y_AXIS];
-  return o;
-}
-
-Offset
-complex_divide (Offset z1, Offset z2)
-{
-  z2 = complex_conjugate (z2);
-  Offset z = complex_multiply (z1, z2);
-  z *= 1 / z2.length ();
-  return z;
-}
-
-Offset
-complex_exp (Offset o)
-{
-  Real s = sin (o[Y_AXIS]);
-  Real c = cos (o[Y_AXIS]);
-
-  Real r = exp (o[X_AXIS]);
-
-  return Offset (r * c, r * s);
-}
-
-Real
-Offset::arg () const
+static inline Real
+atan2d (Real y, Real x)
 {
-  return atan2 (coordinate_a_[Y_AXIS], coordinate_a_[X_AXIS]);
+  return atan2 (y, x) * (180.0 / M_PI);
 }
 
 Real
 Offset::angle_degrees () const
 {
-  return arg () * 180 / M_PI;
+  Real x = coordinate_a_ [X_AXIS];
+  Real y = coordinate_a_ [Y_AXIS];
+
+  // We keep in the vicinity of multiples of 45 degrees here: this is
+  // where straightforward angles for straightforward angular
+  // relations are most expected.  The factors of 2 employed in the
+  // comparison are not really perfect for that: sqrt(2)+1 would be
+  // the factor giving exact windows of 45 degrees rather than what we
+  // have here.  It's just that 2 is likely to generate nicer code
+  // than 2.4 and the exact handover does not really matter.
+  //
+  // Comparisons here are chosen appropriately to let infinities end
+  // up in their "exact" branch.  As opposed to the normal atan2
+  // function behavior, this makes "competing" infinities result in
+  // NAN angles.
+  if (y < 0.0)
+    {
+      if (2*x < -y)
+        if (-x > -2*y)          // x < 0, y < 0, |x| > |2y|
+          return -180 + atan2d (-y, -x);
+        else if (-2*x >= -y)    // x < 0, y < 0, |y| < |2x| <= |4y|
+          return -135 + atan2d (x - y, -y - x);
+        else                    // y < 0, |y| >= |2x|
+          return -90 + atan2d (x, -y);
+      else if (x <= -2*y)       // x > 0, y < 0, |y| <= |2x| < |4y|
+        return -45 + atan2d (x + y, x - y);
+      // Drop through for y < 0, x > |2y|
+    }
+  else if (y > 0.0)
+    {
+      if (2*x < y)
+        if (-x > 2*y)           // x < 0, y >= 0, |x| > |2y|
+          return 180 - atan2d (y, -x);
+        else if (-2*x >= y)     // x < 0, y >= 0, |y| < |2x| <= |4y|
+          return 135 - atan2d (x + y, y - x);
+        else                    // y >= 0, |y| >= |2x|
+          return 90 - atan2d (x, y);
+      else if (x <= 2*y)        // x >= 0, y >= 0, |y| < |2x| < |4y|
+        return 45 - atan2d (x - y, x + y);
+      // Drop through for y > 0, x > |2y|
+    }
+  else
+    // we return 0 for (0,0).  NAN would be an option but is a
+    // nuisance for getting back to rectangular coordinates.  Strictly
+    // speaking, this argument would be just as valid for (+inf.0,
+    // +inf.0), but then infinities are already an indication of a
+    // problem in LilyPond.
+    return (x < 0.0) ? 180 : 0;
+  return atan2d (y, x);
 }
+
+
 /**
    euclidian vector length / complex modulus
 */
@@ -126,3 +149,39 @@ Offset::swapped () const
 {
   return Offset (coordinate_a_[Y_AXIS], coordinate_a_[X_AXIS]);
 }
+
+Offset
+offset_directed (Real angle)
+{
+  if (angle <= -360.0 || angle >= 360.0)
+    angle = fmod (angle, 360.0);
+  // Now |angle| < 360.0, and the absolute size is not larger than
+  // before, so we haven't lost precision.
+  if (angle <= -180.0)
+    angle += 360.0;
+  else if (angle > 180.0)
+    angle -= 360.0;
+  // Now -180.0 < angle <= 180.0 and we still haven't lost precision.
+  // We don't work with angles greater than 45 degrees absolute in
+  // order to minimize how rounding errors of M_PI/180 affect the
+  // result.  That way, at least angles that are a multiple of 90
+  // degree deliver the expected results.
+  //
+  // Sign of the sine is chosen to avoid -0.0 in results.  This
+  // version delivers exactly equal magnitude on x/y for odd multiples
+  // of 45 degrees at the cost of losing some less obvious invariants.
+
+  if (angle > 0)
+    if (angle > 90)
+      return Offset (sin ((90 - angle) * M_PI/180.0),
+                     sin ((180 - angle) * M_PI/180.0));
+    else
+      return Offset (sin ((90 - angle) * M_PI/180.0),
+                     sin (angle * M_PI/180.0));
+  else if (angle < -90)
+    return Offset (sin ((90 + angle) * M_PI/180.0),
+                   sin ((-180 - angle) * M_PI/180.0));
+  else
+    return Offset (sin ((90 + angle) * M_PI/180.0),
+                   sin (angle * M_PI/180.0));
+}
diff --git a/input/regression/remove-layer-symbol.ly b/input/regression/remove-layer-symbol.ly
new file mode 100644 (file)
index 0000000..d6fa93d
--- /dev/null
@@ -0,0 +1,65 @@
+\version "2.19.48"
+
+\header {
+  texidoc = "The @code{VerticalAxisGroup.remove-layer} property
+  can be used to keep staves alive with reference to other staves
+  in the @code{Keep_alive_together_engraver} group."
+}
+
+\layout {
+  indent = 40\mm
+  short-indent = 15\mm
+}
+
+\score {
+  <<
+    \new Staff \with {
+      instrumentName = "Continuous"
+      shortInstrumentName = "cont"
+    } { \repeat unfold 104 g'4 \bar "|." }
+    \new StaffGroup \with {
+      \consists Keep_alive_together_engraver
+    } <<
+      \new Staff \with {
+        keepAliveInterfaces = #'()
+        instrumentName = \markup \center-column { "Alive with A or B" }
+        shortInstrumentName = "with A or B"
+        \override VerticalAxisGroup.remove-empty = ##t
+        \override VerticalAxisGroup.remove-first = ##t
+        \override VerticalAxisGroup.remove-layer = #'any
+      } { \repeat unfold 104 c''4 }
+      \new Staff \with {
+        instrumentName = "A"
+        shortInstrumentName = "A"
+        \override VerticalAxisGroup.remove-empty = ##t
+        \override VerticalAxisGroup.remove-first = ##t
+        \override VerticalAxisGroup.remove-layer = ##f
+      } {
+        \repeat unfold 16 c'4
+        R1*4
+        \repeat unfold 16 c'4
+        R1*14
+      }
+      \new Staff \with {
+        keepAliveInterfaces = #'()
+        instrumentName = \markup \center-column { "Alive with A" }
+        shortInstrumentName = "with A"
+        \override VerticalAxisGroup.remove-empty = ##t
+        \override VerticalAxisGroup.remove-first = ##t
+        \override VerticalAxisGroup.remove-layer = #'above
+      } { \repeat unfold 104 c''4 }
+      \new Staff \with {
+        instrumentName = "B"
+        shortInstrumentName = "B"
+        \override VerticalAxisGroup.remove-empty = ##t
+        \override VerticalAxisGroup.remove-first = ##t
+        \override VerticalAxisGroup.remove-layer = ##f
+      } {
+        R1*8
+        \repeat unfold 16 c'4
+        R1*13
+        c'1
+      }
+    >>
+  >>
+}
index 461dd2f824cbfdeb0d8e8598b895e5ffd00bbb2b..a7f891c048ff65f8a97384c80b8f2caf15c24269 100644 (file)
@@ -8,11 +8,17 @@ in @code{Score}-context.
 @code{FretBoards} will print those micro-tones only if they can be found in the
 chosen settings for @code{stringTunings}, otherwise a warning (surpressed here)
 will be printed and an empty @code{FretBoard} returned.  Which should be the
-case here for the first pitch: @code{gih}"
+case for the last four of the examples pitches.
+Micro-tones assigned to strings work nicely."
 }
 
 #(ly:set-option 'warning-as-error #f)
-#(ly:expect-warning (_ "No string for pitch ~a (given frets ~a)") #{ gih #} '())
+#(for-each
+  (lambda (pitch)
+    (ly:expect-warning (_ "No string for pitch "))
+    (ly:expect-warning (_ "Requested string for pitch requires negative fret"))
+    (ly:expect-warning (_ "Ignoring string request and recalculating.")))
+  (iota 4))
 
 \layout {
   \context {
@@ -24,8 +30,7 @@ case here for the first pitch: @code{gih}"
 custom-tuning = \stringTuning <e, a, d ges beh eeh'>
 
 mus = \relative {
-  gih4
-  eeses'
+  eeses'4
   eeseh
   ees
   eeh
@@ -34,6 +39,10 @@ mus = \relative {
   eis
   eisih
   eisis
+  geseh,,\6
+  geh\6
+  gih\6
+  gisih\6
 }
 
 <<
index 5ba2e59279ec992270fb443d8faaf022ca3eb6b6..95da047a067bd5ced57ba29f53a0a2ee93405bbe 100644 (file)
@@ -215,7 +215,7 @@ Arpeggio::brew_chord_slur (SCM smob)
   Real height_limit = 1.5;
   Real ratio = .33;
   Bezier curve = slur_shape (dy, height_limit, ratio);
-  curve.rotate (M_PI / 2);
+  curve.rotate (90.0);
 
   Stencil mol (Lookup::slur (curve, lt, lt, dash_definition));
   mol.translate_axis (heads[LEFT], Y_AXIS);
index a20530c0f3e0afdbd8adc7aa12a8a8802aa9115c..a50f2904bc0b00e4a497c16c908b13cabf38d96b 100644 (file)
@@ -1280,7 +1280,7 @@ Beam::rest_collision_callback (SCM smob, SCM prev_offset)
 
   Real offset = robust_scm2double (prev_offset, 0.0);
   Interval rest_extent = rest->extent (rest, Y_AXIS);
-  rest_extent.translate (offset + rest->get_parent (Y_AXIS)->relative_coordinate (common_y, Y_AXIS));
+  rest_extent.translate (offset + rest->parent_relative (common_y, Y_AXIS));
 
   Real rest_dim = rest_extent[d];
   Real minimum_distance
index b202d45dd6262f5d52df2590bdc2a93846e68579..eacd4fe6a44e95f224d6a9f4894455198167710a 100644 (file)
@@ -38,9 +38,9 @@ scale (vector<Offset> *array, Real x, Real y)
 }
 
 void
-rotate (vector<Offset> *array, Real phi)
+rotate (vector<Offset> *array, Real deg)
 {
-  Offset rot (complex_exp (Offset (0, phi)));
+  Offset rot (offset_directed (deg));
   for (vsize i = 0; i < array->size (); i++)
     (*array)[i] = complex_multiply (rot, (*array)[i]);
 }
@@ -322,9 +322,9 @@ Bezier::scale (Real x, Real y)
 }
 
 void
-Bezier::rotate (Real phi)
+Bezier::rotate (Real deg)
 {
-  Offset rot (complex_exp (Offset (0, phi)));
+  Offset rot (offset_directed (deg));
   for (int i = 0; i < CONTROL_COUNT; i++)
     control_[i] = complex_multiply (rot, control_[i]);
 }
index c9db28baf93e8bb26ff6810cc28d43770247292e..c069fb7c74c61c8a033c7ec833151c75ffe748a4 100644 (file)
@@ -99,8 +99,7 @@ Fingering_column::do_y_positioning (Grob *me)
         {
           Interval x_ext = fingerings[i]->extent(common[X_AXIS], X_AXIS);
           Interval y_ext = fingerings[i]->extent(fingerings[i], Y_AXIS);
-          Real parent_y = fingerings[i]->get_parent(Y_AXIS)
-                         ->relative_coordinate(common[Y_AXIS], Y_AXIS);
+          Real parent_y = fingerings[i]->parent_relative (common[Y_AXIS], Y_AXIS);
 
           // Checking only between sequential neighbors, seems good enough
           if (!intersection(x_ext, prev_x_ext).is_empty())
index eafa66288efdab93c9ab72bf49a3831c749c24b2..23a1cafae48730885fb7068346750e1f114ec35a 100644 (file)
@@ -338,14 +338,16 @@ Grob::relative_coordinate (Grob const *refp, Axis a) const
 
   /* We catch PARENT_L_ == nil case with this, but we crash if we did
      not ask for the absolute coordinate (ie. REFP == nil.)  */
-  Real off = get_offset (a);
-  if (refp == dim_cache_[a].parent_)
-    return off;
 
-  if (dim_cache_[a].parent_ != NULL)
-    off += dim_cache_[a].parent_->relative_coordinate (refp, a);
+  return get_offset (a) + parent_relative (refp, a);
+}
 
-  return off;
+Real
+Grob::parent_relative (Grob const *refp, Axis a) const
+{
+  if (Grob *p = get_parent (a))
+    return p->relative_coordinate (refp, a);
+  return 0.0;
 }
 
 Real
index 06410786a67fc3e770d4efa56c857b787c0ffed7..76207a5c928abb5dfae0bdb788c063931de21cf2 100644 (file)
@@ -190,9 +190,11 @@ Hara_kiri_group_spanner::add_interesting_item (Grob *me, Grob *n)
 ADD_INTERFACE (Hara_kiri_group_spanner,
                "A group spanner that keeps track of interesting items.  If it"
                " doesn't contain any after line breaking, it removes itself"
-               " and all its children.  Children may be prioritized in layers"
-               " via @code{remove-layer}, in which case only the"
-               " lowest-numbered non-empty layer is retained.",
+               " and all its children.  Greater control can be exercised via"
+               " @code{remove-layer} which can prioritize layers so only the"
+               " lowest-numbered non-empty layer is retained; make the layer"
+               " independent of the group; or make it dependent on any other"
+               " member of the group",
 
                /* properties */
                "items-worth-living "
index 959afc5c4ee32cc2a475d8eadee00eb1cf5ecab5..54acce15fc11b818dbec4801ffbfc3d1fd273dd6 100644 (file)
@@ -62,7 +62,7 @@ public:
 };
 
 void scale (vector<Offset> *array, Real xscale, Real yscale);
-void rotate (vector<Offset> *array, Real phi);
+void rotate (vector<Offset> *array, Real deg);
 void translate (vector<Offset> *array, Offset o);
 
 Bezier slur_shape (Real width, Real height_limit,
index a9408f09a2ac1cbc6beb21a9766526c3d3af5914..5da4dff74ec6107c242754e6c60b2eddefa90848 100644 (file)
@@ -141,6 +141,7 @@ public:
   /* offsets */
   void translate_axis (Real, Axis);
   Real relative_coordinate (Grob const *refp, Axis) const;
+  Real parent_relative (Grob const *refp, Axis) const;
   Real pure_relative_y_coordinate (Grob const *refp, int start, int end);
   Real maybe_pure_coordinate (Grob const *refp, Axis a, bool pure, int start, int end);
 
index 9b1cbe4a23a412b95cb8797e6f7dd8fdc7656704..8931a819c6ff45150ccb229fdec3d06b8c457426 100644 (file)
@@ -22,6 +22,7 @@
 #include "engraver.hh"
 #include "grob.hh"
 #include "grob-array.hh"
+#include "international.hh"
 
 #include "translator.icc"
 
@@ -64,12 +65,44 @@ Keep_alive_together_engraver::finalize ()
         {
           if (i == j)
             continue;
+
+          if (scm_is_symbol (this_layer))
+            {
+              if (scm_is_eq (this_layer, ly_symbol2scm ("any")))
+                {
+                  // layer is kept alive by any other layer
+                  live->add (group_spanners_[j]);
+                  continue;
+                }
+              else if (scm_is_eq (this_layer, ly_symbol2scm ("above")))
+                {
+                  // layer is kept alive by the layer preceding it
+                  if (i == j + 1)
+                    live->add (group_spanners_[j]);
+                  continue;
+                }
+              else if (scm_is_eq (this_layer, ly_symbol2scm ("below")))
+                {
+                  // layer is kept alive by the layer following it
+                  if (i == j - 1)
+                    live->add (group_spanners_[j]);
+                  continue;
+                }
+              else
+                {
+                  group_spanners_[i]->warning (_f ("unknown remove-layer value `%s'",
+                                                   ly_symbol2string (this_layer).c_str ()));
+                  continue;
+                }
+            }
+
           SCM that_layer = group_spanners_[j]->get_property ("remove-layer");
+
           if (scm_is_false (that_layer))
             continue;
           if (!scm_is_integer (this_layer))
             {
-              // Unspecified layers are kept alive by anything else
+              // unset layers are kept alive by all but ignored layers
               live->add (group_spanners_[j]);
               continue;
             }
index f23b58e3084be45de601b5b04f771cf2fb4b3aab..bc0895339fea3c996e08a71891c0090cbea2e96c 100644 (file)
@@ -70,7 +70,7 @@ Line_interface::make_trill_line (Grob *me,
     }
   while (len + elt_len < dz.length ());
 
-  line.rotate (dz.arg (), Offset (LEFT, CENTER));
+  line.rotate (dz.angle_degrees (), Offset (LEFT, CENTER));
   line.translate (from);
 
   return line;
index 3e592516c588bc765cdfe451931bd56da2122e8b..d7b6b8d26e9bc81c5eada2ab7911128c1de26a2d 100644 (file)
@@ -417,9 +417,9 @@ Lookup::slur (Bezier curve, Real curvethick, Real linethick,
       calculate the offset for the two beziers that make the sandwich
       for the slur
   */
-  Real alpha = (curve.control_[3] - curve.control_[0]).arg ();
+  Offset dir = (curve.control_[3] - curve.control_[0]).direction ();
   Bezier back = curve;
-  Offset perp = curvethick * complex_exp (Offset (0, alpha + M_PI / 2)) * 0.5;
+  Offset perp = 0.5 * curvethick * Offset (-dir[Y_AXIS], dir[X_AXIS]);
   back.control_[1] += perp;
   back.control_[2] += perp;
 
index 16e2929a6699001fd029f7e43548097ec62031c6..52551e8b5286452342d4eae53dbc1f9396efef36 100644 (file)
@@ -220,7 +220,7 @@ Side_position_interface::aligned_side (Grob *me, Axis a, bool pure, int start, i
       // skyline will likely be of infinite width anyway
       // and we don't want to prematurely trigger H spacing
       Real xc = a == X_AXIS || (pure && dynamic_cast<Spanner *> (me))
-                ? me->get_parent (X_AXIS)->relative_coordinate (common[X_AXIS], X_AXIS)
+                ? me->parent_relative (common[X_AXIS], X_AXIS)
                 : me->relative_coordinate (common[X_AXIS], X_AXIS);
       // same here, for X_AXIS spacing, if it's happening, it should only be
       // before line breaking.  because there is no thing as "pure" x spacing,
@@ -274,7 +274,7 @@ Side_position_interface::aligned_side (Grob *me, Axis a, bool pure, int start, i
            if (unsmob<Skyline_pair> (sp))
              {
                Real xc = pure && dynamic_cast<Spanner *> (e)
-                         ? e->get_parent (X_AXIS)->relative_coordinate (common[X_AXIS], X_AXIS)
+                         ? e->parent_relative (common[X_AXIS], X_AXIS)
                          : e->relative_coordinate (common[X_AXIS], X_AXIS);
                // same logic as above
                // we assume horizontal spacing is always pure
index dc453a97294fc130b3ec49378d21bdaec3924893..9eb4ef83bd03c74581d9da08b5664c1a062c9c54 100644 (file)
@@ -90,7 +90,7 @@ fit_factor (Offset dz_unit, Offset dz_perp, Real close_to_edge_length,
   Real fit_factor = 0.0;
   Offset x0 = curve.control_[0];
   curve.translate (-x0);
-  curve.rotate (-dz_unit.arg ());
+  curve.rotate (-dz_unit.angle_degrees ());
   curve.scale (1, d);
 
   Interval curve_xext;
index 2d4865e19095aa0f4e983b83ad002e6d90d022db..a3dad6fb5e9785888b05b119ac5320b24c0b36b0 100644 (file)
@@ -740,7 +740,7 @@ Slur_score_state::enumerate_attachments (Drul_array<Real> end_ys) const
                 }
             }
 
-          dz = os[RIGHT] - os[LEFT];
+          dz = (os[RIGHT] - os[LEFT]).direction ();
           for (LEFT_and_RIGHT (d))
             {
               if (extremes_[d].slur_head_
@@ -752,7 +752,7 @@ Slur_score_state::enumerate_attachments (Drul_array<Real> end_ys) const
                      TODO: parameter */
                   os[d][X_AXIS]
                   -= dir_ * extremes_[d].slur_head_x_extent_.length ()
-                     * sin (dz.arg ()) / 3;
+                    * dz[Y_AXIS] / 3;
                 }
             }
 
index 747217c847024b993b307555edcca46c85b025d1..ee12c53f3668a951fbf4160b86f30fcf5e74f047 100644 (file)
@@ -260,6 +260,7 @@ make_partial_ellipse_boxes (vector<Box> &boxes,
   expr = scm_cdr (expr);
   Real y_rad = robust_scm2double (scm_car (expr), 0.0);
   expr = scm_cdr (expr);
+  Offset rad (x_rad, y_rad);
   Real start = robust_scm2double (scm_car (expr), 0.0);
   expr = scm_cdr (expr);
   Real end = robust_scm2double (scm_car (expr), 0.0);
@@ -270,12 +271,10 @@ make_partial_ellipse_boxes (vector<Box> &boxes,
   expr = scm_cdr (expr);
   bool fill = to_boolean (scm_car (expr));
   //////////////////////
-  start = M_PI * start / 180;
-  end = M_PI * end / 180;
   if (end == start)
-    end += (2 * M_PI);
-  Offset sp (cos (start) * x_rad, sin (start) * y_rad);
-  Offset ep (cos (end) * x_rad, sin (end) * y_rad);
+    end += 360;
+  Offset sp (offset_directed (start).scale (rad));
+  Offset ep (offset_directed (end).scale (rad));
   //////////////////////
   Drul_array<vector<Offset> > points;
   int quantization = max (1, (int) (((x_rad * trans.xx) + (y_rad * trans.yy)) * M_PI / QUANTIZATION_UNIT));
@@ -284,7 +283,7 @@ make_partial_ellipse_boxes (vector<Box> &boxes,
       for (vsize i = 0; i < 1 + (vsize) quantization; i++)
         {
           Real ang = linear_map (start, end, 0, quantization, i);
-          Offset pt (cos (ang) * x_rad, sin (ang) * y_rad);
+          Offset pt (offset_directed (ang).scale (rad));
           Offset inter = pt + d * get_normal ((th/2) * pt.direction ());
           pango_matrix_transform_point (&trans, &inter[X_AXIS], &inter[Y_AXIS]);
           points[d].push_back (inter);
@@ -316,7 +315,7 @@ make_partial_ellipse_boxes (vector<Box> &boxes,
   if (th > 0.0)
     {
       // beg line cap
-      Offset pt (cos (start) * x_rad, sin (start) * y_rad);
+      Offset pt (offset_directed (start).scale (rad));
       create_path_cap (boxes,
                        buildings,
                        trans,
@@ -325,7 +324,7 @@ make_partial_ellipse_boxes (vector<Box> &boxes,
                        -get_normal (pt));
 
       // end line cap
-      pt = Offset (cos (end) * x_rad, sin (end) * y_rad);
+      pt = offset_directed (end).scale (rad);
       create_path_cap (boxes,
                        buildings,
                        trans,
index c8d87439d67452e497049886b7cd25bf55cfa194..5c43189e0bc713305d51245cee254b97021300d0 100644 (file)
 #include "font-metric.hh"
 #include "libc-extension.hh"
 #include "lookup.hh"
+#include "offset.hh"
 #include "stencil.hh"
 
+/*
+ * A few general helpers in degrees
+ */
+
+LY_DEFINE (ly_angle, "ly:angle",
+           1, 1, 0, (SCM x, SCM y),
+           "Calculates angle in degrees of given vector.  With one argument,"
+           " @var{x} is a number pair indicating the vector.  With two"
+           " arguments, @var{x} and @var{y} specify the respective coordinates.")
+{
+  Offset off;
+  if (SCM_UNBNDP (y)) {
+    LY_ASSERT_TYPE (is_number_pair, x, 1);
+    off = ly_scm2offset (x);
+  } else {
+    LY_ASSERT_TYPE (scm_is_number, x, 1);
+    LY_ASSERT_TYPE (scm_is_number, y, 2);
+    off = Offset (scm_to_double (x), scm_to_double (y));
+  }
+  return scm_from_double (off.angle_degrees ());
+}
+
+LY_DEFINE (ly_length, "ly:length",
+           1, 1, 0, (SCM x, SCM y),
+           "Calculates magnitude of given vector.  With one argument,"
+           " @var{x} is a number pair indicating the vector.  With two"
+           " arguments, @var{x} and @var{y} specify the respective coordinates.")
+{
+  Offset off;
+  if (SCM_UNBNDP (y)) {
+    LY_ASSERT_TYPE (is_number_pair, x, 1);
+    off = ly_scm2offset (x);
+  } else {
+    LY_ASSERT_TYPE (scm_is_number, x, 1);
+    LY_ASSERT_TYPE (scm_is_number, y, 2);
+    off = Offset (scm_to_double (x), scm_to_double (y));
+  }
+  return scm_from_double (off.length ());
+}
+
+LY_DEFINE (ly_directed, "ly:directed",
+           1, 1, 0, (SCM direction, SCM magnitude),
+           "Calculates an @code{(x . y)} pair with optional @var{magnitude}"
+           " (defaulting to @code{1.0}) and @var{direction} specified either"
+           " as an angle in degrees or a coordinate pair giving the direction. "
+           " If @var{magnitude} is a pair, the respective coordinates are"
+           " scaled independently, useful for ellipse drawings.")
+{
+  Offset res;
+  if (scm_is_pair (direction))
+    {
+      LY_ASSERT_TYPE (is_number_pair, direction, 1);
+      res = ly_scm2offset (direction).direction ();
+    }
+  else
+    {
+      LY_ASSERT_TYPE (scm_is_number, direction, 1);
+      res = offset_directed (scm_to_double (direction));
+    }
+  if (SCM_UNBNDP (magnitude))
+    return ly_offset2scm (res);
+  if (scm_is_pair (magnitude))
+    {
+      LY_ASSERT_TYPE (is_number_pair, magnitude, 2);
+      return ly_offset2scm (res.scale (ly_scm2offset (magnitude)));
+    }
+  LY_ASSERT_TYPE (scm_is_number, magnitude, 2);
+  return ly_offset2scm (scm_to_double (magnitude) * res);
+}
+
+
 /*
   TODO: naming add/combine.
 */
index 0cf49296f0b460f444eaad29b7941b2ab99d248e..5e568c98dbd8efb38dd963f15a8313a242759b0d 100644 (file)
@@ -80,7 +80,7 @@ Stencil::extent_box () const
 void
 Stencil::rotate (Real a, Offset off)
 {
-  rotate_degrees (a * 180 / M_PI, off);
+  rotate_degrees (a, off);
 }
 
 /*
@@ -121,7 +121,7 @@ Stencil::rotate_degrees_absolute (Real a, Offset absolute_off)
   pts.push_back (Offset (shifted_box.x ().at (RIGHT), shifted_box.y ().at (UP)));
   pts.push_back (Offset (shifted_box.x ().at (LEFT), shifted_box.y ().at (UP)));
 
-  const Offset rot = complex_exp (Offset (0, a * M_PI / 180.0));
+  const Offset rot (offset_directed (a));
   dim_.set_empty ();
   for (vsize i = 0; i < pts.size (); i++)
     dim_.add_point (pts[i] * rot + absolute_off);
index 17e1194de80762822da92ed5e7d8767bc6a8a7d0..340b017723753e5431ecce6379129f65ad212caf 100644 (file)
@@ -540,7 +540,7 @@ Tuplet_bracket::calc_position_and_height (Grob *me_grob, Real *offset, Real *dy)
           if (Grob *beam = Stem::get_beam (stems[side]))
             (void) beam->get_property ("quantized-positions");
           poss[side] = stems[side]->extent (stems[side], Y_AXIS)[get_grob_direction (stems[side])]
-                       + stems[side]->get_parent (Y_AXIS)->relative_coordinate (commony, Y_AXIS);
+                       + stems[side]->parent_relative (commony, Y_AXIS);
         }
 
       *dy = poss[RIGHT] - poss[LEFT];
index 5768d8b5f08482bd0f8d8ca24e88e65560bfb00c..6424d756e5df23de2536f1474577d27864071615 100644 (file)
@@ -23,7 +23,7 @@ That's it.  For more information, visit http://lilypond.org .
 
 %}
 
-\version "2.19.47"  % necessary for upgrading to future LilyPond versions.
+\version "2.19.48"  % necessary for upgrading to future LilyPond versions.
 
 \header{
   title = "A scale in LilyPond"
index 0dae0bf064795892e9a1091ea2f0afe555df12be..77503b4ff8c65bae67b8afb428767a2cd4803179 100644 (file)
@@ -32,7 +32,7 @@ Good luck with LilyPond!  Happy engraving.
 
 %}
 
-\version "2.19.47"  % necessary for upgrading to future LilyPond versions.
+\version "2.19.48"  % necessary for upgrading to future LilyPond versions.
 
 \header{
   title = "A scale in LilyPond"
index 90a2fe5b71e5e42e8d70e14b6c2a02a87b5a694a..404ab880432de8b9dd17e044e2b6a86f36e89976 100644 (file)
@@ -1 +1 @@
-See http://git.savannah.gnu.org/gitweb/?p=lilypond.git;a=log;h=refs/tags/release/2.19.47-1
+See http://git.savannah.gnu.org/gitweb/?p=lilypond.git;a=log;h=refs/tags/release/2.19.48-1
index 0a3bba837699e07af8c62cbc2e38deb838847b14..3f56d350509a774884f5ce9060a970186c2bac88 100644 (file)
@@ -1,7 +1,32 @@
-commit 753d6200e9ae51f0a98186478beff2d00d63a62b
-Merge: fc5b145 2e0077b
+commit fd22d6c4d857718d0046dc2b8b802b9ddff13cb5
 Author: Phil Holmes <mail@philholmes.net>
-Date:   Tue Aug 30 11:23:53 2016 +0100
+Date:   Tue Sep 13 11:09:38 2016 +0100
 
-    Update release/unstable with recent changes
+    Release: bump Welcome versions.
 
+diff --git a/ly/Welcome-to-LilyPond-MacOS.ly b/ly/Welcome-to-LilyPond-MacOS.ly
+index 5768d8b..6424d75 100644
+--- a/ly/Welcome-to-LilyPond-MacOS.ly
++++ b/ly/Welcome-to-LilyPond-MacOS.ly
+@@ -23,7 +23,7 @@ That's it.  For more information, visit http://lilypond.org .
+ %}
+-\version "2.19.47"  % necessary for upgrading to future LilyPond versions.
++\version "2.19.48"  % necessary for upgrading to future LilyPond versions.
+ \header{
+   title = "A scale in LilyPond"
+diff --git a/ly/Welcome_to_LilyPond.ly b/ly/Welcome_to_LilyPond.ly
+index 0dae0bf..77503b4 100644
+--- a/ly/Welcome_to_LilyPond.ly
++++ b/ly/Welcome_to_LilyPond.ly
+@@ -32,7 +32,7 @@ Good luck with LilyPond!  Happy engraving.
+ %}
+-\version "2.19.47"  % necessary for upgrading to future LilyPond versions.
++\version "2.19.48"  % necessary for upgrading to future LilyPond versions.
+ \header{
+   title = "A scale in LilyPond"
index 965a48bf9215b8280a1145498e140538b1adada3..c51faefffdb8b0127e163f3302a60c1b704a8411 100644 (file)
@@ -6,10 +6,10 @@
 #, fuzzy
 msgid ""
 msgstr ""
-"Project-Id-Version: lilypond 2.19.47\n"
+"Project-Id-Version: lilypond 2.19.48\n"
 "Report-Msgid-Bugs-To: http://post.gmane.org/post.php?group=gmane.comp.gnu."
 "lilypond.bugs\n"
-"POT-Creation-Date: 2016-08-13 13:37+0100\n"
+"POT-Creation-Date: 2016-09-13 11:07+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -2046,7 +2046,7 @@ msgstr ""
 msgid "failed redirecting stderr to `%s'"
 msgstr ""
 
-#: general-scheme.cc:482 output-ps.scm:48
+#: general-scheme.cc:482
 msgid "Found infinity or nan in output.  Substituting 0.0"
 msgstr ""
 
@@ -2107,7 +2107,7 @@ msgstr ""
 msgid "%d: %s"
 msgstr ""
 
-#: grob.cc:487
+#: grob.cc:489
 #, c-format
 msgid "ignored infinite %s-offset"
 msgstr ""
@@ -2150,6 +2150,11 @@ msgstr ""
 msgid "position unknown"
 msgstr ""
 
+#: keep-alive-together-engraver.cc:93
+#, c-format
+msgid "unknown remove-layer value `%s'"
+msgstr ""
+
 #: key-engraver.cc:197
 msgid "Incomplete keyAlterationOrder for key signature"
 msgstr ""
@@ -3087,7 +3092,7 @@ msgstr ""
 msgid "%s without a cause"
 msgstr ""
 
-#: slur-engraver.cc:322
+#: slur-engraver.cc:320
 #, c-format
 msgid "cannot end %s"
 msgstr ""
@@ -3594,17 +3599,17 @@ msgstr ""
 msgid "not a valid duration string: ~a - ignoring"
 msgstr ""
 
-#: define-music-types.scm:798
+#: define-music-types.scm:796
 #, scheme-format
 msgid "symbol expected: ~S"
 msgstr ""
 
-#: define-music-types.scm:801
+#: define-music-types.scm:799
 #, scheme-format
 msgid "cannot find music object: ~S"
 msgstr ""
 
-#: define-music-types.scm:821
+#: define-music-types.scm:819
 #, scheme-format
 msgid "bad make-music argument: ~S"
 msgstr ""
@@ -3779,19 +3784,19 @@ msgstr ""
 msgid "Music unsuitable for output-def"
 msgstr ""
 
-#: lily-library.scm:920
+#: lily-library.scm:914
 msgid ""
 "Find the index between @var{start} and @var{end} (an integer)\n"
 "which produces the closest match to @var{target-val} if\n"
 "applied to function @var{getter}."
 msgstr ""
 
-#: lily-library.scm:1014
+#: lily-library.scm:1008
 #, scheme-format
 msgid "unknown unit: ~S"
 msgstr ""
 
-#: lily-library.scm:1039
+#: lily-library.scm:1033
 #, scheme-format
 msgid "no \\version statement found, please add~afor future compatibility"
 msgstr ""
@@ -3901,6 +3906,10 @@ msgstr ""
 msgid "negative replication count; ignoring"
 msgstr ""
 
+#: modal-transforms.scm:289
+msgid "Dangling tie in \\retrograde"
+msgstr ""
+
 #: music-functions.scm:319
 #, scheme-format
 msgid "invalid tremolo repeat count: ~a"
@@ -3976,12 +3985,12 @@ msgstr ""
 msgid "conflicting tag group ~a"
 msgstr ""
 
-#: output-ps.scm:290 output-svg.scm:539
+#: output-ps.scm:271 output-svg.scm:539
 #, scheme-format
 msgid "unknown line-cap-style: ~S"
 msgstr ""
 
-#: output-ps.scm:295 output-svg.scm:545
+#: output-ps.scm:276 output-svg.scm:545
 #, scheme-format
 msgid "unknown line-join-style: ~S"
 msgstr ""
@@ -4069,25 +4078,25 @@ msgstr ""
 msgid "No open string for pitch ~a"
 msgstr ""
 
-#: translation-functions.scm:442 translation-functions.scm:454
+#: translation-functions.scm:450 translation-functions.scm:462
 #, scheme-format
 msgid "Requested string for pitch requires negative fret: string ~a pitch ~a"
 msgstr ""
 
-#: translation-functions.scm:445
+#: translation-functions.scm:453
 msgid "Ignoring string request and recalculating."
 msgstr ""
 
-#: translation-functions.scm:457
+#: translation-functions.scm:465
 msgid "Ignoring note in tablature."
 msgstr ""
 
-#: translation-functions.scm:482
+#: translation-functions.scm:490
 #, scheme-format
 msgid "No string for pitch ~a (given frets ~a)"
 msgstr ""
 
-#: translation-functions.scm:598
+#: translation-functions.scm:606
 #, scheme-format
 msgid ""
 "No label for fret ~a (on string ~a);\n"
index 7ca44b6f3d3fd8bdb494b6a0f23dff71b95eb65f..d55ab4c8c788449af838d45b2afd55b9b1e8247c 100644 (file)
@@ -809,12 +809,16 @@ number, the quicker the slur attains its @code{height-limit}.")
 interesting items.")
      (remove-first ,boolean? "Remove the first staff of an orchestral
 score?")
-     (remove-layer ,integer? "The @code{Keep_alive_together_engraver}
-removes all @code{VerticalAxisGroup} grobs with a @code{remove-layer}
-larger than the smallest retained @code{remove-layer}.  Set to
-@code{#f} to make a layer invisible to the
-@code{Keep_alive_together_engraver}, set to @code{'()} to have it not
-participate in the layering decisions.")
+     (remove-layer ,key? "When set as a positive integer, the
+@code{Keep_alive_together_engraver} removes all
+@code{VerticalAxisGroup} grobs with a @code{remove-layer} larger than
+the smallest retained @code{remove-layer}. Set to @code{#f} to make a
+layer independent of the @code{Keep_alive_together_engraver}. Set to
+@code{'()}, the layer does not participate in the layering decisions.
+The property can also be set as a symbol for common behaviors:
+@code{#'any} to keep the layer alive with any other layer in the
+group; @code{#'above} or @code{#'below} to keep the layer alive with
+the context immediately before or after it, respectively.")
      (replacement-alist ,list? "Alist of strings.
 The key is a string of the pattern to be replaced.  The value is a
 string of what should be displayed.  Useful for ligatures.")
index 574b85437eb251b12c02e6e3f24f6bdbecd3173e..bbbe3cc53acebcd12ad2406cf9fde2a50b07a8e1 100644 (file)
@@ -776,14 +776,8 @@ right (@var{dir}=+1)."
 
 (define-public (polar->rectangular radius angle-in-degrees)
   "Return polar coordinates (@var{radius}, @var{angle-in-degrees})
-as rectangular coordinates @ode{(x-length . y-length)}."
-
-  (let ((complex (make-polar
-                  radius
-                  (degrees->radians angle-in-degrees))))
-    (cons
-     (real-part complex)
-     (imag-part complex))))
+as rectangular coordinates @code{(x-length . y-length)}."
+  (ly:directed angle-in-degrees radius))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; string
index 70b13848e4aa6ad898bac04f79d33c80dfdaf838..6d3ab63c2fcf30dd78370cd7cb97e9b458abbe0e 100644 (file)
              (scm framework-ps)
              (lily))
 
-;;; helper functions, not part of output interface
-;;;
-
-
-;; ice-9 format uses a lot of memory
-;; using simple-format almost halves lilypond cell usage
-
-(define (str4 num)
-  (if (or (nan? num) (inf? num))
-      (begin
-        (ly:warning (_ "Found infinity or nan in output.  Substituting 0.0"))
-        (if (ly:get-option 'strict-infinity-checking)
-            (exit 1))
-        "0.0")
-      (ly:number->string num)))
-
-(define (number-pair->string4 numpair)
-  (ly:format "~4l" numpair))
-
 ;;;
 ;;; Lily output interface, PostScript implementation --- cleanup and docme
 ;;;
index 22f8648c31e8c0dcaacdad9a4894c6ef057bd0fc..0ed0deff0a24817edc4f53b42fb902313f0e75bc 100644 (file)
@@ -427,13 +427,21 @@ the current tuning?"
                          (ly:warning (_ "No open string for pitch ~a")
                                      pitch)))
                    ;; here we handle assigned strings
-                   (let ((this-fret
-                          (calc-fret pitch string tuning))
-                         (handle-negative
-                          (ly:context-property context
-                                               'handleNegativeFrets
-                                               'recalculate)))
-                     (cond ((or (and (>= this-fret 0) (integer? this-fret))
+                   (let* ((this-fret
+                           (calc-fret pitch string tuning))
+                          (possible-fret?
+                           (and (>= this-fret 0)
+                                (if (and
+                                      (ly:context-property
+                                        context 'supportNonIntegerFret #f)
+                                      (null? rest))
+                                    (integer? (truncate this-fret))
+                                    (integer? this-fret))))
+                          (handle-negative
+                           (ly:context-property context
+                                                'handleNegativeFrets
+                                                'recalculate)))
+                     (cond ((or possible-fret?
                                 (eq? handle-negative 'include))
                             (set-fret! pitch-entry string finger))
                            ((eq? handle-negative 'recalculate)