]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/mensural-ligature-engraver.cc
Web-ja: update introduction
[lilypond.git] / lily / mensural-ligature-engraver.cc
index 62799ec55c663aa99c13408e4b2a7c1e9053b7bf..482538c720588537f16291fc2b243b46514fe7ad 100644 (file)
@@ -1,7 +1,7 @@
 /*
   This file is part of LilyPond, the GNU music typesetter.
 
-  Copyright (C) 2002--2012 Juergen Reuter <reuter@ipd.uka.de>,
+  Copyright (C) 2002--2015 Juergen Reuter <reuter@ipd.uka.de>,
   Pal Benko <benkop@freestart.hu>
 
   LilyPond is free software: you can redistribute it and/or modify
@@ -59,26 +59,22 @@ protected:
   virtual Spanner *create_ligature_spanner ();
   virtual void build_ligature (Spanner *ligature,
                                vector<Grob_info> const &primitives);
-  DECLARE_TRANSLATOR_LISTENER (ligature);
 
 public:
   TRANSLATOR_DECLARATIONS (Mensural_ligature_engraver);
+  TRANSLATOR_INHERIT (Coherent_ligature_engraver);
 
 private:
   void transform_heads (vector<Grob_info> const &primitives);
   void propagate_properties (Spanner *ligature,
-                             vector<Grob_info> const &primitives);
-  void fold_up_primitives (vector<Grob_info> const &primitives);
+                             vector<Grob_info> const &primitives,
+                             Real &min_length);
+  void fold_up_primitives (vector<Grob_info> const &primitives,
+                           Real &min_length);
 };
 
-IMPLEMENT_TRANSLATOR_LISTENER (Mensural_ligature_engraver, ligature);
-void
-Mensural_ligature_engraver::listen_ligature (Stream_event *ev)
-{
-  Ligature_engraver::listen_ligature (ev);
-}
-
-Mensural_ligature_engraver::Mensural_ligature_engraver ()
+Mensural_ligature_engraver::Mensural_ligature_engraver (Context *c)
+  : Coherent_ligature_engraver (c)
 {
   brew_ligature_primitive_proc
     = Mensural_ligature::brew_ligature_primitive_proc;
@@ -127,7 +123,7 @@ Mensural_ligature_engraver::transform_heads (vector<Grob_info> const &primitives
           continue;
         }
 
-      int pitch = unsmob_pitch (nr->get_property ("pitch"))->steps ();
+      int pitch = unsmob<Pitch> (nr->get_property ("pitch"))->steps ();
       int prim = 0;
 
       if (at_beginning)
@@ -180,7 +176,7 @@ Mensural_ligature_engraver::transform_heads (vector<Grob_info> const &primitives
             }
           // b. descendens longa or brevis
           else if (i < s - 1
-                   && (unsmob_pitch (primitives[i + 1].event_cause ()
+                   && (unsmob<Pitch> (primitives[i + 1].event_cause ()
                                      ->get_property ("pitch"))->steps () < pitch)
                    && duration_log > -3)
             {
@@ -273,7 +269,7 @@ Mensural_ligature_engraver::transform_heads (vector<Grob_info> const &primitives
                   /*
                     breve: check whether descending
                   */
-                  int const next_pitch = unsmob_pitch
+                  int const next_pitch = unsmob<Pitch>
                                          (next_info.event_cause ()->get_property ("pitch"))->steps ();
                   if (next_pitch < pitch)
                     /*
@@ -338,7 +334,8 @@ Mensural_ligature_engraver::transform_heads (vector<Grob_info> const &primitives
  */
 void
 Mensural_ligature_engraver::propagate_properties (Spanner *ligature,
-                                                  vector<Grob_info> const &primitives)
+                                                  vector<Grob_info> const &primitives,
+                                                  Real &min_length)
 {
   Real thickness
     = robust_scm2double (ligature->get_property ("thickness"), 1.3);
@@ -352,6 +349,7 @@ Mensural_ligature_engraver::propagate_properties (Spanner *ligature,
     = Font_interface::get_default_font (ligature)->
       find_by_name ("noteheads.sM3ligmensural").extent (X_AXIS).length ();
 
+  min_length = 0.0;
   Item *prev_primitive = NULL;
   for (vsize i = 0; i < primitives.size (); i++)
     {
@@ -364,9 +362,11 @@ Mensural_ligature_engraver::propagate_properties (Spanner *ligature,
         {
         case MLP_BREVIS:
         case MLP_LONGA:
+          min_length += head_width;
           primitive->set_property ("head-width", scm_from_double (head_width));
           break;
         case MLP_MAXIMA:
+          min_length += maxima_head_width;
           primitive->set_property ("head-width",
                                    scm_from_double (maxima_head_width));
           break;
@@ -379,6 +379,7 @@ Mensural_ligature_engraver::propagate_properties (Spanner *ligature,
           {
             SCM flexa_scm = primitive->get_property ("flexa-width");
             Real const flexa_width = robust_scm2double (flexa_scm, 2.0);
+            min_length += flexa_width + thickness;
             SCM head_width = scm_from_double (0.5 * (flexa_width + thickness));
             primitive->set_property ("head-width", head_width);
             prev_primitive->set_property ("head-width", head_width);
@@ -395,7 +396,8 @@ Mensural_ligature_engraver::propagate_properties (Spanner *ligature,
 }
 
 void
-Mensural_ligature_engraver::fold_up_primitives (vector<Grob_info> const &primitives)
+Mensural_ligature_engraver::fold_up_primitives (vector<Grob_info> const &primitives,
+                                                Real &min_length)
 {
   Item *first = 0;
   Real distance = 0.0;
@@ -418,7 +420,7 @@ Mensural_ligature_engraver::fold_up_primitives (vector<Grob_info> const &primiti
       Real head_width = scm_to_double (current->get_property ("head-width"));
       distance += head_width - thickness;
 
-      if (Rhythmic_head::dot_count (current) > 0)
+      if (size_t const dot_count = Rhythmic_head::dot_count (current))
         /*
           Move dots above/behind the ligature.
           dots should also avoid staff lines.
@@ -454,6 +456,8 @@ Mensural_ligature_engraver::fold_up_primitives (vector<Grob_info> const &primiti
               else if (delta == 1 || delta == -1)
                 vert_shift -= delta * staff_space;
             }
+          else
+            min_length += head_width * dot_count;
 
           dot_gr->translate_axis (vert_shift, Y_AXIS);
 
@@ -470,13 +474,29 @@ void
 Mensural_ligature_engraver::build_ligature (Spanner *ligature,
                                             vector<Grob_info> const &primitives)
 {
+  /*
+    the X extent of the actual graphics representing the ligature;
+    less space than that means collision
+  */
+  Real min_length;
+
   transform_heads (primitives);
-  propagate_properties (ligature, primitives);
-  fold_up_primitives (primitives);
+  propagate_properties (ligature, primitives, min_length);
+  fold_up_primitives (primitives, min_length);
+
+  if (robust_scm2double (ligature->get_property ("minimum-length"), 0.0)
+      < min_length)
+    ligature->set_property ("minimum-length", scm_from_double (min_length));
 }
 
-ADD_ACKNOWLEDGER (Mensural_ligature_engraver, rest);
-ADD_ACKNOWLEDGER (Mensural_ligature_engraver, ligature_head);
+
+void
+Mensural_ligature_engraver::boot ()
+{
+  ADD_LISTENER (Mensural_ligature_engraver, ligature);
+  ADD_ACKNOWLEDGER (Mensural_ligature_engraver, rest);
+  ADD_ACKNOWLEDGER (Mensural_ligature_engraver, ligature_head);
+}
 
 ADD_TRANSLATOR (Mensural_ligature_engraver,
                 /* doc */