]> git.donarmstrong.com Git - lilypond.git/commitdiff
Fix collisions between hairpins and dynamic text spanner bounds.
authorNeil Puttock <n.puttock@gmail.com>
Fri, 18 Sep 2009 21:01:24 +0000 (22:01 +0100)
committerNeil Puttock <n.puttock@gmail.com>
Fri, 18 Sep 2009 21:01:24 +0000 (22:01 +0100)
* rename 'adjacent-hairpins to 'adjacent-spanners

* add DynamicTextSpanner grobs to 'adjacent-spanners in New_dynamic_engraver

* in Hairpin::print (), use renamed property to catch text spans and apply
  the appropriate amount of bound-padding

* add regression test

input/regression/hairpin-neighboring-span-dynamics.ly [new file with mode: 0644]
lily/hairpin.cc
lily/new-dynamic-engraver.cc
scm/define-grob-properties.scm

diff --git a/input/regression/hairpin-neighboring-span-dynamics.ly b/input/regression/hairpin-neighboring-span-dynamics.ly
new file mode 100644 (file)
index 0000000..d969346
--- /dev/null
@@ -0,0 +1,27 @@
+\version "2.13.4"
+
+\header {
+  texidoc = "Bound padding for hairpins also works with neighboring
+@code{DynamicTextSpanner} grobs.  In this case, @code{bound-padding}
+is not scaled down.
+"
+}
+
+\relative c' {
+  \override Hairpin #'to-barline = ##f
+  c2\>
+  \dimTextDim
+  c2\>
+  \dimHairpin
+  c\> c\! \break
+  \dimTextDim
+  c2\> 
+  \override Hairpin #'bound-padding = #5
+  \dimHairpin
+  c2\>
+  \dimTextDim
+  c2\> c\! \break
+  \crescHairpin
+  c2\< c\<
+  c2\< c\!
+}
index bb4fec084bb66c10c64a2ea724731a9285294448..6403c6224100589d3758482553eca2a6737550c1 100644 (file)
@@ -70,7 +70,7 @@ Hairpin::print (SCM smob)
 
   broken[RIGHT] = broken[RIGHT] && me->broken_neighbor (RIGHT);
   broken[RIGHT] = broken[RIGHT] && me->broken_neighbor (RIGHT)->is_live ();
-  
+
   if (broken[RIGHT])
     {
       Spanner *next = me->broken_neighbor (RIGHT);
@@ -86,8 +86,8 @@ Hairpin::print (SCM smob)
     Use the height and thickness of the hairpin when making a circled tip
   */
   bool circled_tip = ly_scm2bool (me->get_property ("circled-tip"));
-  Real height = robust_scm2double (me->get_property ("height"), 0.2) *
-               Staff_symbol_referencer::staff_space (me);
+  Real height = robust_scm2double (me->get_property ("height"), 0.2)
+    * Staff_symbol_referencer::staff_space (me);
   /*
     FIXME: 0.525 is still just a guess...
   */
@@ -95,7 +95,7 @@ Hairpin::print (SCM smob)
   Real thick = 1.0;
   if (circled_tip)
     thick = robust_scm2double (me->get_property ("thickness"), 1.0)
-           * Staff_symbol_referencer::line_thickness (me);
+      * Staff_symbol_referencer::line_thickness (me);
 
   do
     {
@@ -117,37 +117,47 @@ Hairpin::print (SCM smob)
          else
            {
              bool neighbor_found = false;
-             extract_grob_set (me, "adjacent-hairpins", pins);
-             for (vsize i = 0; i < pins.size (); i++)
+             Spanner *adjacent;
+             extract_grob_set (me, "adjacent-spanners", neighbors);
+             for (vsize i = 0; i < neighbors.size (); i++)
                {
                  /*
                    FIXME: this will fuck up in case of polyphonic
                    notes in other voices. Need to look at note-columns
                    in the current staff/voice.
                  */
-
-                 Spanner *pin = dynamic_cast<Spanner *> (pins[i]);
-                 if (pin
-                     && (pin->get_bound (LEFT)->get_column () == b->get_column ()
-                         || pin->get_bound (RIGHT)->get_column () == b->get_column ()))
-                   neighbor_found = true;
+                 adjacent = dynamic_cast<Spanner *> (neighbors[i]);
+                 if (adjacent
+                     && (adjacent->get_bound (-d)->get_column ()
+                         == b->get_column ()))
+                   {
+                     neighbor_found = true;
+                     break;
+                   }
                }
 
              Interval e = robust_relative_extent (b, common, X_AXIS);
              if (neighbor_found)
                {
-                 /*
-                   Handle back-to-back hairpins with a circle in the middle
-                 */
-                 if (circled_tip && (grow_dir != d))
-                   x_points[d] = e.center () + d * (rad - thick / 2.0);
-                 /*
-                   If we're hung on a paper column, that means we're not
-                   adjacent to a text-dynamic, and we may move closer. We
-                   make the padding a little smaller, here.
-                 */
+                 if (Hairpin::has_interface (adjacent))
+                   {
+                     /*
+                       Handle back-to-back hairpins with a circle in the middle
+                     */
+                     if (circled_tip && (grow_dir != d))
+                       x_points[d] = e.center () + d * (rad - thick / 2.0);
+                     /*
+                       If we're hung on a paper column, that means we're not
+                       adjacent to a text-dynamic, and we may move closer. We
+                       make the padding a little smaller, here.
+                     */
+                     else
+                       x_points[d] = e.center () - d * padding / 3;
+                   }
+                 // Our neighbor is a dynamic text spanner, so add the
+                 // same amount of padding as for text dynamics
                  else
-                   x_points[d] = e.center () - d * padding / 3;
+                   x_points[d] = e[-d] - d * padding;
                }
              else
                {
@@ -156,10 +166,10 @@ Hairpin::print (SCM smob)
                    x_points[d] = e[-d];
                  else
                    x_points[d] = e[d];
-                 
+
                  Item *bound = me->get_bound (d);
                  if (bound->is_non_musical (bound))
-                   x_points[d] -=  d * padding;
+                   x_points[d] -= d * padding;
                }
            }
        }
@@ -218,16 +228,16 @@ Hairpin::print (SCM smob)
   if (circled_tip)
     {
       Box extent (Interval (-rad, rad), Interval (-rad, rad));
-      
+
       /* Hmmm, perhaps we should have a Lookup::circle () method? */
       Stencil circle (extent,
-                    scm_list_4 (ly_symbol2scm ("circle"),
-                                scm_from_double (rad),
-                                scm_from_double (thick),
-                                SCM_BOOL_F));
+                     scm_list_4 (ly_symbol2scm ("circle"),
+                                 scm_from_double (rad),
+                                 scm_from_double (thick),
+                                 SCM_BOOL_F));
 
       /*
-       don't add another circle the hairpin is broken
+       don't add another circle if the hairpin is broken
       */
       if (!broken[tip_dir])
        mol.add_at_edge (X_AXIS, tip_dir, Stencil (circle), 0);
@@ -243,7 +253,7 @@ ADD_INTERFACE (Hairpin,
               "A hairpin crescendo or decrescendo.",
 
               /* properties */
-              "adjacent-hairpins "
+              "adjacent-spanners "
               "circled-tip "
               "bound-padding "
               "grow-direction "
index 235dc178d912c2f41d2863d914a14eed2209692b..489fcf5ea6c0142b97e2a18dab9fdd5eb79e4e6f 100644 (file)
@@ -1,15 +1,12 @@
 /* 
   new-dynamic-engraver.cc -- implement New_dynamic_engraver
-  
+
   source file of the GNU LilyPond music typesetter
-  
+
   (c) 2008--2009 Han-Wen Nienhuys <hanwen@lilypond.org>
-  
 */
 
-
 #include "engraver.hh"
-
 #include "hairpin.hh"
 #include "international.hh"
 #include "item.hh"
@@ -35,13 +32,14 @@ protected:
   virtual void finalize ();
 
 private:
-  SCM get_property_setting (Stream_event *evt, char const *evprop, char const *ctxprop);
+  SCM get_property_setting (Stream_event *evt, char const *evprop,
+                           char const *ctxprop);
   string get_spanner_type (Stream_event *ev);
 
   Drul_array<Stream_event *> accepted_spanevents_drul_;
   Spanner *current_spanner_;
   Spanner *finished_spanner_;
-  
+
   Item *script_;
   Stream_event *script_event_;
   Stream_event *current_span_event_;
@@ -74,7 +72,9 @@ New_dynamic_engraver::listen_span_dynamic (Stream_event *ev)
 }
 
 SCM
-New_dynamic_engraver::get_property_setting (Stream_event *evt, char const *evprop, char const *ctxprop)
+New_dynamic_engraver::get_property_setting (Stream_event *evt,
+                                           char const *evprop,
+                                           char const *ctxprop)
 {
   SCM spanner_type = evt->get_property (evprop);
   if (spanner_type == SCM_EOL)
@@ -86,7 +86,9 @@ void
 New_dynamic_engraver::process_music ()
 {
   if (current_spanner_
-      && (accepted_spanevents_drul_[STOP] || script_event_ || accepted_spanevents_drul_[START]))
+      && (accepted_spanevents_drul_[STOP]
+         || script_event_
+         || accepted_spanevents_drul_[START]))
     {
       Stream_event *ender = accepted_spanevents_drul_[STOP];
       if (!ender)
@@ -94,7 +96,7 @@ New_dynamic_engraver::process_music ()
 
       if (!ender)
        ender = accepted_spanevents_drul_[START];
-      
+
       finished_spanner_ = current_spanner_;
       announce_end_grob (finished_spanner_, ender->self_scm ());
       current_spanner_ = 0;
@@ -107,7 +109,7 @@ New_dynamic_engraver::process_music ()
 
       string start_type = get_spanner_type (current_span_event_);
       SCM cresc_type = get_property_setting (current_span_event_, "span-type",
-                                       (start_type + "Spanner").c_str ());
+                                            (start_type + "Spanner").c_str ());
 
       if (cresc_type == ly_symbol2scm ("text"))
        {
@@ -116,11 +118,9 @@ New_dynamic_engraver::process_music ()
                            accepted_spanevents_drul_[START]->self_scm ());
 
          SCM text = get_property_setting (current_span_event_, "span-text",
-                                       (start_type + "Text").c_str ());
+                                          (start_type + "Text").c_str ());
          if (Text_interface::is_markup (text))
-           {
-             current_spanner_->set_property ("text", text);
-           }
+           current_spanner_->set_property ("text", text);
        }
       else
        {
@@ -132,16 +132,17 @@ New_dynamic_engraver::process_music ()
            }
          current_spanner_ = make_spanner ("Hairpin",
                                           current_span_event_->self_scm ());
-         if (finished_spanner_)
-           {
-             Pointer_group_interface::add_grob (finished_spanner_,
-                                                ly_symbol2scm ("adjacent-hairpins"),
-                                                current_spanner_);
-
-             Pointer_group_interface::add_grob (current_spanner_,
-                                                ly_symbol2scm ("adjacent-hairpins"),
-                                                finished_spanner_);
-           }
+       }
+      if (finished_spanner_)
+       {
+         if (Hairpin::has_interface (finished_spanner_))
+           Pointer_group_interface::add_grob (finished_spanner_,
+                                              ly_symbol2scm ("adjacent-spanners"),
+                                              current_spanner_);
+         if (Hairpin::has_interface (current_spanner_))
+           Pointer_group_interface::add_grob (current_spanner_,
+                                              ly_symbol2scm ("adjacent-spanners"),
+                                              finished_spanner_);
        }
     }
 
@@ -161,26 +162,24 @@ New_dynamic_engraver::process_music ()
            set_nested_property (current_spanner_,
                                 scm_list_3 (ly_symbol2scm ("bound-details"),
                                             ly_symbol2scm ("left"),
-                                            ly_symbol2scm ("attach-dir")
-                                            ),
+                                            ly_symbol2scm ("attach-dir")),
                                 scm_from_int (RIGHT));
-
        }
     }
 }
 
-
-
 void
 New_dynamic_engraver::stop_translation_timestep ()
 {
   if (finished_spanner_ && !finished_spanner_->get_bound (RIGHT))
-    finished_spanner_->set_bound (RIGHT,
-                                 unsmob_grob (get_property ("currentMusicalColumn")));
+    finished_spanner_
+      ->set_bound (RIGHT,
+                  unsmob_grob (get_property ("currentMusicalColumn")));
 
   if (current_spanner_ && !current_spanner_->get_bound (LEFT))
-    current_spanner_->set_bound (LEFT,
-                                unsmob_grob (get_property ("currentMusicalColumn")));
+    current_spanner_
+      ->set_bound (LEFT,
+                  unsmob_grob (get_property ("currentMusicalColumn")));
   script_ = 0;
   script_event_ = 0;
   accepted_spanevents_drul_.set (0, 0);
@@ -216,6 +215,7 @@ New_dynamic_engraver::get_spanner_type (Stream_event *ev)
     type = "crescendo";
   else
     programming_error ("unknown dynamic spanner type");
+
   return type;
 }
 
index 0ff4f7641a0f713f90bc19dac75fa780bda10873..b9cf4ed3a20ff876816b9ff1bfca70cfaf86fffb 100644 (file)
@@ -884,8 +884,8 @@ constructed from a whole number of squiggles.")
      (accidental-grob ,ly:grob? "The accidental for this note.")
      (accidental-grobs ,list? "An alist with @code{(@var{notename} .
 @var{groblist})} entries.")
-     (adjacent-hairpins ,ly:grob-array? "An array of directly neighboring
-hairpins.")
+     (adjacent-spanners ,ly:grob-array? "An array of directly neighboring
+dynamic spanners.")
      (all-elements ,ly:grob-array? "An array of all grobs in this line.  Its
 function is to protect objects from being garbage collected.")
      (arpeggio ,ly:grob? "A pointer to an @code{Arpeggio} object.")