]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/kievan-ligature-engraver.cc
Imported Upstream version 2.18.0
[lilypond.git] / lily / kievan-ligature-engraver.cc
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 */
+                ""
+               );