]> git.donarmstrong.com Git - lilypond.git/commitdiff
Creates support for melismas ("ligatures") in Kievan notation via the use of a ligatu...
authorAleksandr Andreev <aleksandr.andreev@gmail.com>
Fri, 22 Feb 2013 19:13:32 +0000 (20:13 +0100)
committerMike Solomon <mike@apollinemike.com>
Fri, 22 Feb 2013 19:13:32 +0000 (20:13 +0100)
Author:    Aleksandr Andreev <aleksandr.andreev@gmail.com>

lily/coherent-ligature-engraver.cc
lily/include/kievan-ligature.hh [new file with mode: 0644]
lily/kievan-ligature-engraver.cc [new file with mode: 0644]
lily/kievan-ligature.cc [new file with mode: 0644]
lily/ligature-engraver.cc
ly/engraver-init.ly
scm/define-grobs.scm

index 843c5208c0dfd78b570c9ebbe41d4427a16bee9f..3e2915e719674c28021273dad98233b09363c9b2 100644 (file)
@@ -40,9 +40,9 @@
  *
  * - delegate actual creation of ligature to concrete subclass,
  *
- * - collect all accidentals that occur within the ligature and put
- * them at the left side of the ligature (TODO; see function
- * collect_accidentals ()),
+ * - except in Kievan notation, collect all accidentals that occur
+ * within the ligature and put them at the left side of the ligature
+ * (TODO; see function collect_accidentals ()),
  *
  * - collapse superflous space after each ligature (TODO).
  *
@@ -135,6 +135,9 @@ Coherent_ligature_engraver::collect_accidentals (Spanner *,
                                                  vector<Grob_info> const &)
 {
   /* TODO */
+  /* NOTE: if implementing such a function, note that in Kievan notation,
+   * the B-flat accidental should not be "collected", but rather prints
+   * immediately before the note head as usual. */
 }
 
 void
diff --git a/lily/include/kievan-ligature.hh b/lily/include/kievan-ligature.hh
new file mode 100644 (file)
index 0000000..cb6494c
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+  This file is part of LilyPond, the GNU music typesetter.
+
+  Copyright (C) 2013 Aleksandr Andreev <aleksandr.andreev@gmail.com>
+
+  LilyPond is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LilyPond is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef KIEVAN_LIGATURE_HH
+#define KIEVAN_LIGATURE_HH
+
+#include "lily-proto.hh"
+#include "grob-interface.hh"
+
+struct Kievan_ligature
+{
+  DECLARE_SCHEME_CALLBACK (print, (SCM));
+  DECLARE_GROB_INTERFACE ();
+};
+
+#endif /* KIEVAN_LIGATURE_HH */
diff --git a/lily/kievan-ligature-engraver.cc b/lily/kievan-ligature-engraver.cc
new file mode 100644 (file)
index 0000000..92b9848
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+  This file is part of LilyPond, the GNU music typesetter.
+
+  Copyright (C) 2013 Aleksandr Andreev <aleksandr.andreev@gmail.com>
+
+  LilyPond is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LilyPond is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "coherent-ligature-engraver.hh"
+#include "font-interface.hh"
+#include "international.hh"
+#include "kievan-ligature.hh"
+#include "paper-column.hh"
+#include "rhythmic-head.hh"
+#include "spanner.hh"
+#include "stream-event.hh"
+#include "warn.hh"
+
+#include "translator.icc"
+
+class Kievan_ligature_engraver : public Coherent_ligature_engraver
+{
+
+protected:
+  virtual Spanner *create_ligature_spanner ();
+  virtual void build_ligature (Spanner *ligature,
+                               vector<Grob_info> const &primitives);
+  DECLARE_TRANSLATOR_LISTENER (ligature);
+
+public:
+  TRANSLATOR_DECLARATIONS (Kievan_ligature_engraver);
+
+private:
+  void fold_up_primitives (vector<Grob_info> const &primitives, Real padding, Real &min_length);
+};
+
+IMPLEMENT_TRANSLATOR_LISTENER (Kievan_ligature_engraver, ligature);
+void
+Kievan_ligature_engraver::listen_ligature (Stream_event *ev)
+{
+  Ligature_engraver::listen_ligature (ev);
+}
+
+Kievan_ligature_engraver::Kievan_ligature_engraver ()
+{
+
+}
+
+Spanner *
+Kievan_ligature_engraver::create_ligature_spanner ()
+{
+  return make_spanner ("KievanLigature", SCM_EOL);
+}
+
+void
+Kievan_ligature_engraver::fold_up_primitives (vector<Grob_info> const &primitives,
+                                               Real padding, Real &min_length)
+{
+  Item *first = 0;
+  Real accumul_acc_space = 0.0;
+  // start us off with some padding on the left
+  min_length = padding;
+
+  for (vsize i = 0; i < primitives.size (); i++)
+    {
+      Item *current = dynamic_cast<Item *> (primitives[i].grob ());
+      Interval my_ext = current->extent (current, X_AXIS);
+      Real head_width = my_ext.length ();
+      if (i == 0)
+         first = current;
+
+      // must keep track of accidentals in spacing problem
+      Grob *acc_gr = unsmob_grob (current->get_object ("accidental-grob"));
+      if (acc_gr && i > 0)
+        {
+           Interval acc_ext = acc_gr->extent (acc_gr, X_AXIS);
+           accumul_acc_space += acc_ext.length();
+        }
+
+      move_related_items_to_column (current, first->get_column (),
+                                    min_length);
+
+      // check if we have any dots
+      if (size_t const dot_count = Rhythmic_head::dot_count (current))
+        {
+          Grob *dot_gr = Rhythmic_head::get_dots (current);
+
+          head_width += Font_interface::get_default_font (current)->
+              find_by_name ("dots.dotkievan").extent (X_AXIS).length() -
+              0.5 * (padding - accumul_acc_space);
+
+          dot_gr->translate_axis (0.5 * (padding - accumul_acc_space), X_AXIS);
+        }
+
+      // add more padding if we have an accidental coming up
+      if (i < primitives.size () - 1)
+        {
+           Item *next = dynamic_cast<Item *> (primitives[i + 1].grob ());
+           Grob *acc_gr = unsmob_grob (next->get_object ("accidental-grob"));
+           if (acc_gr)
+             {
+                Interval acc_ext = acc_gr->extent (acc_gr, X_AXIS);
+                padding += acc_ext.length();
+             }
+        }
+
+      min_length += head_width + padding - accumul_acc_space;
+
+    }
+
+}
+
+void
+Kievan_ligature_engraver::build_ligature (Spanner *ligature,
+                                            vector<Grob_info> const &primitives)
+{
+  Real min_length;
+
+  Real padding = robust_scm2double (ligature->get_property ("padding"), 0.0);
+  fold_up_primitives (primitives, padding, 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 (Kievan_ligature_engraver, rest);
+ADD_ACKNOWLEDGER (Kievan_ligature_engraver, ligature_head);
+
+ADD_TRANSLATOR (Kievan_ligature_engraver,
+                /* doc */
+                "Handle @code{Kievan_ligature_events} by glueing Kievan"
+                " heads together.",
+
+                /* create */
+                "KievanLigature ",
+
+                /* read */
+                "",
+
+                /* write */
+                ""
+               );
diff --git a/lily/kievan-ligature.cc b/lily/kievan-ligature.cc
new file mode 100644 (file)
index 0000000..21ea23e
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+  This file is part of LilyPond, the GNU music typesetter.
+
+  Copyright (C) 2013 Aleksandr Andreev <aleksandr.andreev@gmail.com>
+
+  LilyPond is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LilyPond is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "kievan-ligature.hh"
+
+#include "international.hh"
+#include "item.hh"
+#include "warn.hh"
+
+MAKE_SCHEME_CALLBACK (Kievan_ligature, print, 1);
+SCM
+Kievan_ligature::print (SCM)
+{
+  return SCM_EOL;
+}
+
+ADD_INTERFACE (Kievan_ligature,
+               "A kievan ligature.",
+
+               /* properties */
+               "primitive "
+               "padding "
+              );
index fb6f54c7064e97d6352d73a8417b599f58822c66..297337a976eb404c7b4096eb26307fb29c537578 100644 (file)
  * produce a single connected graphical object of fixed width,
  * consisting of noteheads and other primitives.  Space may be
  * inserted only after each ligature, if necessary, but in no case
- * between the primitives of the ligature.  Accidentals have to be put
+ * between the primitives of the ligature. The same approach is
+ * used for Kievan notation ligatures, or, rather melismas.
+ * Though these are not single connected objects, they behave much
+ * in the same way and have a fixed, small amount of space between
+ * noteheads. Except in Kievan "ligatures", accidentals have to be put
  * to the left of the ligature, and not to the left of individual
- * noteheads.  Class Coherent_ligature_engraver is the common
+ * noteheads. In Kievan ligatures, the B-flat may be part of the
+ * ligature itself. Class Coherent_ligature_engraver is the common
  * superclass for all of these engravers.
  *
  * The second category is for engravers that are relaxed in the sense
index a7754ef67c54aa095ee6b3639c55c57b523a5142..58ee39a12304b4acf61aa4bbad4c76b683235829 100644 (file)
@@ -1139,6 +1139,9 @@ accommodated for typesetting a piece in Petrucci style."
  \description "Same as @code{Voice} context, except that it is
 accommodated for typesetting a piece in Kievan style."
 
+  \remove "Ligature_bracket_engraver"
+  \consists "Kievan_ligature_engraver"
+
  %% Set glyph styles.
  \override NoteHead.style = #'kievan
  \override Stem.X-offset = #stem::kievan-offset-callback
index 915a51ca72c4619e9b8c25977a16221ccbf25b08..ad014bce4489ff566b632bddcf3ba75c473b52a2 100644 (file)
                                pure-from-neighbor-interface
                                staff-symbol-referencer-interface))))))
 
+    (KievanLigature
+     . (
+       (springs-and-rods . ,ly:spanner::set-spacing-rods)
+       (stencil . ,ly:kievan-ligature::print)
+       (padding . 0.5)
+       (meta . ((class . Spanner)
+                (interfaces . (font-interface
+                               kievan-ligature-interface))))))
 
    (LaissezVibrerTie
      . (