]> git.donarmstrong.com Git - lilypond.git/commitdiff
Merge remote branch 'origin/release/unstable' into HEAD
authorPhil Holmes <mail@philholmes.net>
Wed, 29 Aug 2012 14:59:49 +0000 (15:59 +0100)
committerPhil Holmes <mail@philholmes.net>
Wed, 29 Aug 2012 14:59:49 +0000 (15:59 +0100)
29 files changed:
Documentation/contributor/programming-work.itexi
Documentation/contributor/quick-start.itexi
Documentation/contributor/regressions.itexi
Documentation/contributor/source-code.itexi
Documentation/de/notation/spacing.itely
Documentation/es/notation/spacing.itely
Documentation/fr/notation/spacing.itely
Documentation/ja/notation/spacing.itely
input/regression/accidental-fingering-collision.ly [new file with mode: 0644]
input/regression/fingering-column.ly [new file with mode: 0644]
input/regression/hairpin-clef.ly
input/regression/hairpin-key-signature.ly
input/regression/text-script-vertical-skylines.ly
input/regression/tuplet-bracket-vertical-skylines.ly
input/regression/volta-bracket-vertical-skylines.ly
lily/beam-collision-engraver.cc
lily/fingering-column-engraver.cc [new file with mode: 0644]
lily/fingering-column.cc [new file with mode: 0644]
lily/grob.cc
lily/include/fingering-column.hh [new file with mode: 0644]
lily/include/grob.hh
lily/include/skyline-pair.hh
lily/include/skyline.hh
lily/side-position-interface.cc
lily/skyline-pair.cc
lily/skyline.cc
ly/engraver-init.ly
scm/define-grob-interfaces.scm
scm/define-grobs.scm

index d72424ab4c17df1fefb22917797e2fe819e616ac..de22c42ec57453d5f20fbfb23ed57a898aa85ac0 100644 (file)
@@ -979,7 +979,7 @@ for all errors and defines functions for displaying scheme objects
 (ps), grobs (pgrob), and parsed music expressions (pmusic).
 
 @example
-file ~/lilypond-git/build/out/bin/lilypond
+file $LILYPOND_GIT/build/out/bin/lilypond
 b programming_error
 b Grob::programming_error
 
index 2172677054daedd1d6866936609af73dfa6b5b90..4788379f4ce1b1c56a94d2e1c98da385dd418173 100644 (file)
@@ -282,7 +282,7 @@ the software directly. See @ref{Manually installing lily-git.tcl}.
 
 @item
 Finally, lily-git is always part of the LilyPond source code and is
-located in @file{~/lilypond-git/scripts/auxillar/lily-git.tcl}.
+located in @file{$LILYPOND_GIT/scripts/auxillar/lily-git.tcl}.
 
 @end itemize
 
@@ -311,7 +311,7 @@ lily-git with this information.
 @item
 Click on the @qq{Get source} button.
 
-A directory called @file{lilypond-git/} is now created within
+A directory called @file{$LILYPOND_GIT} is now created within
 your home directory and the complete source code will start to be
 downloaded into it.
 
@@ -328,7 +328,7 @@ minutes -- it could be an intermittant network problem.  If the
 problem persists, please ask for help.}
 
 @item
-Close the lily-git GUI and navigate to the @file{lilypond-git/}
+Close the lily-git GUI and navigate to the @file{$LILYPOND_GIT}
 directory to view and edit the source files.
 
 @end enumerate
@@ -444,7 +444,7 @@ the command-line; see @ref{Uploading a patch for review}.
 hopelessly confused!}
 
 The button labeled @qq{Abort changes -- Reset to origin} will copy
-all changed files to a subdirectory of @file{lilypond-git/} named
+all changed files to a subdirectory of @file{$LILYPOND_GIT} named
 @file{aborted_edits/}, and will reset the repository to the
 current state of the remote repository (at @code{git.sv.gnu.org}).
 
@@ -465,7 +465,7 @@ text.  This should take less than a minute.
 @c we heavily recommend the out-of-tree build; do not change this!
 
 @example
-cd ~/lilypond-git/
+cd $LILYPOND_GIT
 sh autogen.sh --noconfigure
 mkdir -p build/
 cd build/
@@ -481,14 +481,14 @@ building; this can have a non-negligible effect on compilation
 speed.
 
 @example
-cd ~/lilypond-git/build/
+cd $LILYPOND_GIT/build/
 make
 @end example
 
 You may run the compiled @code{lilypond} with:
 
 @example
-cd ~/lilypond-git/build/
+cd $LILYPOND_GIT/build/
 out/bin/lilypond my-file.ly
 @end example
 
@@ -498,7 +498,7 @@ Compiling the documentation is a much more involved process, and
 will likely take 2 to 10 hours.
 
 @example
-cd ~/lilypond-git/build/
+cd $LILYPOND_GIT/build/
 make
 make doc
 @end example
@@ -508,14 +508,14 @@ view the html files by entering the below text; we recommend that
 you bookmark the resulting page:
 
 @example
-firefox ~/lilypond-git/build/out-www/offline-root/index.html
+firefox $LILYPOND_GIT/build/out-www/offline-root/index.html
 @end example
 
 @subsubheading Installing
 
 Don't.  There is no reason to install lilypond within LilyDev.
 All development work can (and should) stay within the
-@file{$HOME/lilypond-git/} directory, and any personal composition
+@file{$LILYPOND_GIT} directory, and any personal composition
 or typesetting work should be done with an official GUB release.
 
 
index 7bca714f2c412b1aa56a77962c98e5fa7731216b..c155a8b923ad946a6beec6aaa2772eb26353935c 100644 (file)
@@ -209,7 +209,7 @@ Run @code{make} with current git master without any of your changes.
 
 @item
 Before making changes to the code, establish a baseline for the comparison by
-going to the @file{lilypond-git/build/} directory and running:
+going to the @file{$LILYPOND_GIT/build/} directory and running:
 
 @example
 make test-baseline
index d3f4f3a11b8dc11e7813f658d286606a46d97c27..72b05175d8d3f2d3dde667a7891b20fea2f737fd 100644 (file)
@@ -93,7 +93,7 @@ files.
 @end enumerate
 
 @warning{Throughout the rest of this manual, most command-line
-input should be entered from @file{~/lilypond-git/}.  This is
+input should be entered from @file{$LILYPOND_GIT}.  This is
 referred to as the @emph{top source directory}.}
 
 Further instructions are in @ref{How to use lily-git}.
@@ -160,7 +160,7 @@ The above command will put the it in @file{~/lilypond-git}, where
 
 @subsubheading Technical details
 
-This creates (within the @file{~/lilypond-git/} directory) a
+This creates (within the @file{$LILYPOND_GIT} directory) a
 subdirectory called @file{.git/}, which Git uses to keep track of
 changes to the repository, among other things.  Normally you don't
 need to access it, but it's good to know it's there.
@@ -171,7 +171,7 @@ need to access it, but it's good to know it's there.
 
 @warning{Throughout the rest of this manual, all command-line
 input should be entered from the top directory of the Git
-repository being discussed (eg. @file{~/lilypond-git/}).  This is
+repository being discussed (eg. @file{$LILYPOND_GIT}).  This is
 referred to as the @emph{top source directory}.}
 
 Before working with the copy of the main LilyPond repository, you
@@ -732,7 +732,7 @@ Already on 'master'
 @end example
 
 By now the source files should be accessible---you should be able
-to edit any files in the @file{lilypond-git/} directory using a
+to edit any files in the @file{$LILYPOND_GIT} directory using a
 text editor of your choice.  But don't start just yet!  Before
 editing any source files, learn how to keep your changes organized
 and prevent problems later---read @ref{Basic Git procedures}.
@@ -1295,7 +1295,7 @@ cl} with the following commands.  If you do not understand any
 question, just answer with a newline (CR).
 
 @example
-cd $HOME/lilypond-git/
+cd $LILYPOND_GIT
 git cl config
 @end example
 
index 97a0404cbe5e521b2c4260fd357638927f9edec1..3eea389a620b26f450f68071684b7cfc78f37edf 100644 (file)
@@ -8,7 +8,7 @@
     Guide, node Updating translation committishes.
 @end ignore
 
-@c \version "2.16.0"
+@c \version "2.17.0"
 
 @c Translators: Till Paala
 
@@ -857,22 +857,22 @@ Standardwerte, die hier nicht aufgelistet sind, finden sich in
 
 @table @code
 
-@item blank-after-score-page-force
-@funindex blank-after-score-page-force
+@item blank-after-score-page-penalty
+@funindex blank-after-score-page-penalty
 
 Die Strafpunke, die erteilt werden, wenn eine leere Seite nach einer
 Partitur und vor der nächsten vorkommt.  Der Standardwert hiervon ist
-kleiner als @code{blank-page-force}, sodass leere Seiten nach einer Partitur
+kleiner als @code{blank-page-penalty}, sodass leere Seiten nach einer Partitur
 leeren Seiten innerhalb einer Partitur vorgezogen werden.
 
-@item blank-last-page-force
-@funindex blank-last-page-force
+@item blank-last-page-penalty
+@funindex blank-last-page-penalty
 
 Die Strafpunkte, wenn eine Partitur auf einer ungeraden Seite
 beendet wird. Standard: @code{0}.
 
-@item blank-page-force
-@funindex blank-page-force
+@item blank-page-penalty
+@funindex blank-page-penalty
 
 Die Strafpunkte, wenn eine leere Seite mitten in einer Partitur
 auftritt.  Das wird nicht benutzt von @code{ly:optimal-breaking},
index 4fd96d97070b29488699415e7ba1f23070ddd22b..d387defecb1946690020cf53b46c1bd3b229f761 100644 (file)
@@ -8,7 +8,7 @@
     Guide, node Updating translation committishes..
 @end ignore
 
-@c \version "2.16.0"
+@c \version "2.17.0"
 
 @ignore
 GDP TODO list
@@ -921,21 +921,21 @@ en el archivo @file{ly/paper-defaults-init.ly}
 
 @table @code
 
-@item blank-after-score-page-force
-@funindex blank-after-score-page-force
+@item blank-after-score-page-penalty
+@funindex blank-after-score-page-penalty
 
 Penalización por tener una página vacía después del final de una
 partitura y antes de la siguiente.  De forma predeterminada, es menor
-que @code{blank-page-force}, de manera que preferimos páginas vacías
+que @code{blank-page-penalty}, de manera que preferimos páginas vacías
 después de las partituras que páginas vacías dentro de una partitura.
 
-@item blank-last-page-force
-@funindex blank-last-page-force
+@item blank-last-page-penalty
+@funindex blank-last-page-penalty
 
 Penalización por terminar la partitura sobre una página impar.
 
-@item blank-page-force
-@funindex blank-page-force
+@item blank-page-penalty
+@funindex blank-page-penalty
 
 Penalización por tener una página vacía en medio de una partitura.  No
 se utiliza por parte de @code{ly:optimal-breaking} porque nunca
index f9465101f850fff556892af044869e6e6ee89ecb..e74b54d57167f0e332956cd191b574d1d729cbde 100644 (file)
@@ -7,7 +7,7 @@
     Guide, node Updating translation committishes..
 @end ignore
 
-@c \version "2.16.0"
+@c \version "2.17.0"
 
 @c Translators: Frédéric Chiasson, Jean-Charles Malahieude
 
@@ -921,22 +921,22 @@ Les valeurs par défaut sont définies dans le fichier
 
 @table @code
 
-@item blank-after-score-page-force
-@funindex blank-after-score-page-force
+@item blank-after-score-page-penalty
+@funindex blank-after-score-page-penalty
 
 Pénalité pour apparition d'une page blanche entre deux partitions.  Sa
 valeur est par défaut inférieure à celle de
-@code{blank-page-force} ; nous préférons qu'une page blanche
+@code{blank-page-penalty} ; nous préférons qu'une page blanche
 s'insère après la fin de la partition plutôt qu'au milieu.
 
-@item blank-last-page-force
-@funindex blank-last-page-force
+@item blank-last-page-penalty
+@funindex blank-last-page-penalty
 
 Pénalité pour fin de partition intervenant sur une page impaire.  La
 valeur par défaut est de @code{0}.
 
-@item blank-page-force
-@funindex blank-page-force
+@item blank-page-penalty
+@funindex blank-page-penalty
 
 Pénalité pour apparition d'une page blanche en cours de partition.
 L'algorithme @code{ly:optimal-breaking} n'en tiendra pas compte
index c71eff7cda10d2ea4ac4bb8097f665f19975b45c..2f395786de46608489b86c081becd884537a0775 100644 (file)
@@ -8,7 +8,7 @@
     Guide, node Updating translation committishes..
 @end ignore
 
-@c \version "2.16.0"
+@c \version "2.17.0"
 
 
 @c Translators: Yoshiki Sawada
@@ -880,20 +880,20 @@ score で使用すべきシステム数です。@c
 
 @table @code
 
-@item blank-after-score-page-force
-@funindex blank-after-score-page-force
+@item blank-after-score-page-penalty
+@funindex blank-after-score-page-penalty
 
 楽譜の後ろ (と次の楽譜の前) に強制的に白紙を挿入します。@c
-デフォルトでは、この値は @code{blank-page-force} よりも小さいため、@c
+デフォルトでは、この値は @code{blank-page-penalty} よりも小さいため、@c
 楽譜の途中ではなく後ろに白紙が挿入されます。
 
-@item blank-last-page-force
-@funindex blank-last-page-force
+@item blank-last-page-penalty
+@funindex blank-last-page-penalty
 
 楽譜の最後が奇数ページの場合、楽譜の後ろに白紙を挿入します。
 
-@item blank-page-force
-@funindex blank-page-force
+@item blank-page-penalty
+@funindex blank-page-penalty
 
 楽譜の途中に強制的に白紙を挿入します。@c
 この値は @code{ly:optimal-breaking} では用いられません。@c
diff --git a/input/regression/accidental-fingering-collision.ly b/input/regression/accidental-fingering-collision.ly
new file mode 100644 (file)
index 0000000..ac7a07e
--- /dev/null
@@ -0,0 +1,13 @@
+\version "2.17.0"
+
+\header {
+  texidoc = "Horizontal @code{Fingering} grobs should not collide with
+accidentals.
+"
+}
+
+\relative c' {
+  \time 2/4
+  \set fingeringOrientations = #'(left)
+  <a-3 cis-4> <a-3 cis!-4> |
+}
\ No newline at end of file
diff --git a/input/regression/fingering-column.ly b/input/regression/fingering-column.ly
new file mode 100644 (file)
index 0000000..be6fe7d
--- /dev/null
@@ -0,0 +1,16 @@
+\version "2.17.1"
+
+\header {
+  texidoc = "Horizontal @code{Fingering} grobs that collide do not intersect.
+Non-intersecting @code{Fingering} grobs are left alone.
+"
+}
+
+\relative c'' {
+   \set fingeringOrientations = #'(left)
+   \override Fingering #'staff-padding = #'()
+   \override Fingering #'add-stem-support = ##f
+   <d-0 c-3 f,-0>4 <d-0 f,-3 e-0>
+   <d^0 c^3 f,-0> <d^0 f,-0> <c^3 f,-0>
+   <d-0 c-0 b-0 a-0 g-0 f-0>
+}
index 8450129f726011c081ff27e64c5d7d8cd83e4756..43acfdf0fbe40ca936efa7d6aa2ad0523dc13425 100644 (file)
@@ -1,4 +1,4 @@
-\version "2.15.28"
+\version "2.16.0"
 
 \header {
   texidoc = "Broken hairpins are not printed too high after treble clefs.
index ff88aa19aaaba672c078009d08c799241d1eb87d..0811099115b3194075e7226f06fb865471ac68da 100644 (file)
@@ -1,4 +1,4 @@
-\version "2.15.28"
+\version "2.16.0"
 
 \header {
   texidoc = "Broken hairpins are not printed too high after key signatures.
index 1eab7f15aae31309bac2125d5326fe3e43565c03..a32818cb6eb30aa5baa9624f0eed0ff636a2e408 100644 (file)
@@ -1,4 +1,4 @@
-\version "2.15.28"
+\version "2.16.0"
 
 \header {
   texidoc = "By default, @code{TextScript} vertical skylines allow
index 74e1d9aeb824773ccf68e5b02a0af0b629f839b5..5dab22c9b3269733ec85a40a5a36b54c65782440 100644 (file)
@@ -1,4 +1,4 @@
-\version "2.15.28"
+\version "2.16.0"
 
 \header {
   texidoc = "Tuplet brackets do not push objects with outside-staff-priority
index 20ebcb95a0bfabcf4a0e79744d89941849e503fc..40b788ddb08b685bbbc40bb34bce10855e7fab44 100644 (file)
@@ -1,4 +1,4 @@
-\version "2.15.28"
+\version "2.16.0"
 
 \header {
   texidoc = "Volta brackets are vertically fit to objects below them.
index b700dc733d39c1ac25d8905186eb8194582139bb..bcd9c698f0239eccea9539e48704c5f6e68c110e 100644 (file)
@@ -34,6 +34,7 @@ protected:
   DECLARE_ACKNOWLEDGER (stem);
   DECLARE_ACKNOWLEDGER (accidental);
   DECLARE_ACKNOWLEDGER (clef);
+  DECLARE_ACKNOWLEDGER (octavate_eight);
   DECLARE_ACKNOWLEDGER (key_signature);
   DECLARE_ACKNOWLEDGER (time_signature);
   DECLARE_ACKNOWLEDGER (beam);
@@ -165,6 +166,12 @@ Beam_collision_engraver::acknowledge_key_signature (Grob_info i)
   covered_grobs_.push_back (i);
 }
 
+void
+Beam_collision_engraver::acknowledge_octavate_eight (Grob_info i)
+{
+  covered_grobs_.push_back (i);
+}
+
 void
 Beam_collision_engraver::acknowledge_time_signature (Grob_info i)
 {
@@ -192,6 +199,7 @@ ADD_ACKNOWLEDGER (Beam_collision_engraver, accidental);
 ADD_ACKNOWLEDGER (Beam_collision_engraver, clef);
 ADD_ACKNOWLEDGER (Beam_collision_engraver, key_signature);
 ADD_ACKNOWLEDGER (Beam_collision_engraver, time_signature);
+ADD_ACKNOWLEDGER (Beam_collision_engraver, octavate_eight);
 ADD_ACKNOWLEDGER (Beam_collision_engraver, flag);
 ADD_ACKNOWLEDGER (Beam_collision_engraver, beam);
 
diff --git a/lily/fingering-column-engraver.cc b/lily/fingering-column-engraver.cc
new file mode 100644 (file)
index 0000000..9cca711
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+  This file is part of LilyPond, the GNU music typesetter.
+
+  Copyright (C) 1999--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+  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 "engraver.hh"
+#include "side-position-interface.hh"
+#include "pointer-group-interface.hh"
+#include "fingering-column.hh"
+#include "item.hh"
+
+#include "translator.icc"
+
+/**
+   Find potentially colliding scripts, and put them in a
+   Fingering_column, that will fix the collisions.  */
+class Fingering_column_engraver : public Engraver
+{
+  Drul_array<Grob *> fingering_columns_;
+  Drul_array<vector<Grob *> > scripts_;
+  vector<Grob *> possibles_;
+
+public:
+  TRANSLATOR_DECLARATIONS (Fingering_column_engraver);
+protected:
+  DECLARE_ACKNOWLEDGER (finger);
+  void process_acknowledged ();
+  void stop_translation_timestep ();
+};
+
+Fingering_column_engraver::Fingering_column_engraver ()
+{
+  for (LEFT_and_RIGHT (d))
+    fingering_columns_[d] = 0;
+}
+
+void
+Fingering_column_engraver::stop_translation_timestep ()
+{
+  for (vsize i = 0; i < possibles_.size (); i++)
+    if (!Item::is_non_musical (possibles_[i]))
+      {
+        if (Side_position_interface::get_axis (possibles_[i]) == X_AXIS)
+          {
+            Direction d = robust_scm2dir (possibles_[i]->get_property ("direction"), CENTER);
+            if (d)
+              scripts_[d].push_back (possibles_[i]);
+            else
+              possibles_[i]->warning ("Cannot add a fingering without a direction.");
+          }
+      }
+
+  for (LEFT_and_RIGHT (d))
+    {
+      if (scripts_[d].size () < 2 && fingering_columns_[d])
+        {
+          fingering_columns_[d]->suicide ();
+          fingering_columns_[d] = 0;
+        }
+      if (fingering_columns_[d])
+        {
+          for (vsize i = 0; i < scripts_[d].size (); i++)
+            Fingering_column::add_fingering (fingering_columns_[d], scripts_[d][i]);
+
+        }
+      scripts_[d].clear ();
+      fingering_columns_[d] = 0;
+    }
+  possibles_.clear ();
+}
+
+void
+Fingering_column_engraver::acknowledge_finger (Grob_info inf)
+{
+  Item *thing = dynamic_cast<Item *> (inf.grob ());
+  if (thing)
+    possibles_.push_back (thing);
+}
+
+void
+Fingering_column_engraver::process_acknowledged ()
+{
+  for (LEFT_and_RIGHT (d))
+    {
+      if (possibles_.size () > 1 && !fingering_columns_[d])
+        fingering_columns_[d] = make_item ("FingeringColumn", SCM_EOL);
+    }
+}
+
+ADD_ACKNOWLEDGER (Fingering_column_engraver, finger);
+ADD_TRANSLATOR (Fingering_column_engraver,
+                /* doc */
+                "Find potentially colliding scripts and put them into a"
+                " @code{FingeringColumn} object; that will fix the collisions.",
+
+                /* create */
+                "FingeringColumn ",
+
+                /* read */
+                "",
+
+                /* write */
+                ""
+               );
diff --git a/lily/fingering-column.cc b/lily/fingering-column.cc
new file mode 100644 (file)
index 0000000..b4e1371
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+  This file is part of LilyPond, the GNU music typesetter.
+
+  Copyright (C) 2002--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+  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 "grob.hh"
+#include "fingering-column.hh"
+#include "pointer-group-interface.hh"
+#include "staff-symbol-referencer.hh"
+#include "item.hh"
+#include "paper-column.hh"
+
+#include <map>
+
+MAKE_SCHEME_CALLBACK (Fingering_column, calc_positioning_done, 1);
+SCM
+Fingering_column::calc_positioning_done (SCM smob)
+{
+  Grob *me = unsmob_grob (smob);
+  Real padding = robust_scm2double (me->get_property ("padding"), 0.0);
+  if (!me->is_live ())
+    return SCM_BOOL_T;
+
+  map<Grob *, bool> shifted;
+
+  Real ss = Staff_symbol_referencer::staff_space (me);
+
+  me->set_property ("positioning-done", SCM_BOOL_T);
+
+  extract_grob_set (me, "fingerings", const_fingerings);
+
+  if (const_fingerings.size () < 2)
+    {
+      me->programming_error ("This FingeringColumn should have never been created.");
+      return SCM_BOOL_T;
+    }
+
+  // order the fingerings from bottom to top
+  vector<Grob *> fingerings;
+  for (vsize i = 0; i < const_fingerings.size (); i++)
+    fingerings.push_back (const_fingerings[i]);
+
+  vector_sort (fingerings, pure_position_less);
+
+  Grob *common[2] = {common_refpoint_of_array (fingerings, me, X_AXIS),
+                     common_refpoint_of_array (fingerings, me, Y_AXIS)};
+
+  for (vsize i = 0; i < fingerings.size (); i++)
+    fingerings[i]->translate_axis (-fingerings[i]->extent (common[Y_AXIS], Y_AXIS).length () / 2, Y_AXIS);
+
+  for (vsize i = min (fingerings.size () - 1, fingerings.size () / 2 + 1); i >= 1; i--)
+    for (vsize j = i; j--;)
+      {
+        Interval ex_i = fingerings[i]->extent (common[X_AXIS], X_AXIS);
+        Interval ex_j = fingerings[j]->extent (common[X_AXIS], X_AXIS);
+        Interval ey_i = fingerings[i]->extent (common[Y_AXIS], Y_AXIS);
+        Interval ey_j = fingerings[j]->extent (common[Y_AXIS], Y_AXIS);
+        Real tval = min (0.0, (ey_i[DOWN] - ey_j[UP] - padding) / 2);
+        if (tval != 0.0 && !intersection (ex_i, ex_j).is_empty ())
+          {
+            if (shifted[fingerings[i]] || shifted[fingerings[j]])
+              fingerings[j]->translate_axis (tval * 2, Y_AXIS);
+            else
+              {
+                fingerings[i]->translate_axis (-tval, Y_AXIS);
+                fingerings[j]->translate_axis (tval, Y_AXIS);
+              }
+            shifted[fingerings[i]] = true;
+            shifted[fingerings[j]] = true;
+          }
+      }
+
+  for (vsize i = fingerings.size () / 2 - 1; i < fingerings.size () - 1; i++)
+    for (vsize j = i + 1; j < fingerings.size (); j++)
+      {
+        Interval ex_i = fingerings[i]->extent (common[X_AXIS], X_AXIS);
+        Interval ex_j = fingerings[j]->extent (common[X_AXIS], X_AXIS);
+        Interval ey_i = fingerings[i]->extent (common[Y_AXIS], Y_AXIS);
+        Interval ey_j = fingerings[j]->extent (common[Y_AXIS], Y_AXIS);
+        Real tval = max (0.0, (ey_i[UP] - ey_j[DOWN] + padding) / 2);
+        if (tval != 0.0 && !intersection (ex_i, ex_j).is_empty ())
+          {
+            if (shifted[fingerings[i]] || shifted[fingerings[j]])
+              fingerings[j]->translate_axis (tval * 2, Y_AXIS);
+            else
+              {
+                fingerings[i]->translate_axis (-tval, Y_AXIS);
+                fingerings[j]->translate_axis (tval, Y_AXIS);
+              }
+            shifted[fingerings[i]] = true;
+            shifted[fingerings[j]] = true;
+          }
+      }
+
+
+  return SCM_BOOL_T;
+}
+
+void
+Fingering_column::add_fingering (Grob *fc, Grob *f)
+{
+  Pointer_group_interface::add_grob (fc, ly_symbol2scm ("fingerings"), f);
+  f->set_parent (fc, X_AXIS);
+  f->set_property ("Y-offset", Grob::x_parent_positioning_proc);
+}
+
+ADD_INTERFACE (Fingering_column,
+               "Makes sure that fingerings placed laterally"
+               " do not collide.",
+
+               /* properties */
+               "padding "
+               "positioning-done "
+              );
index 593b0814a64070a20c83b4dc7c0f2146986f93db..9edf8a2f8a88ff4da6a7c1f260ee947ce7e44453 100644 (file)
@@ -20,6 +20,7 @@
 #include "grob.hh"
 
 #include <cstring>
+#include <set>
 
 #include "align-interface.hh"
 #include "axis-group-interface.hh"
@@ -910,6 +911,20 @@ common_refpoint_of_array (vector<Grob *> const &arr, Grob *common, Axis a)
   return common;
 }
 
+Grob *
+common_refpoint_of_array (set<Grob *> const &arr, Grob *common, Axis a)
+{
+  set<Grob *>::iterator it;
+
+  for (it = arr.begin (); it != arr.end (); it++)
+    if (common)
+      common = common->common_refpoint (*it, a);
+    else
+      common = *it;
+
+  return common;
+}
+
 Interval
 robust_relative_extent (Grob *me, Grob *refpoint, Axis a)
 {
diff --git a/lily/include/fingering-column.hh b/lily/include/fingering-column.hh
new file mode 100644 (file)
index 0000000..6d6bef2
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+  This file is part of LilyPond, the GNU music typesetter.
+
+  Copyright (C) 1999--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+  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 FINGERING_COLUMN_HH
+#define FINGERING_COLUMN_HH
+
+#include "lily-proto.hh"
+#include "grob-interface.hh"
+#include "std-vector.hh"
+
+struct Fingering_column
+{
+  static void add_fingering (Grob *, Grob *);
+  DECLARE_SCHEME_CALLBACK (calc_positioning_done, (SCM));
+  DECLARE_GROB_INTERFACE ();
+};
+
+#endif /* FINGERING_COLUMN_HH */
index 14a7b4792509e1021fc7d87d1b8d3237572c29f5..09cd566ad335b39708990d05ab74894ff2099af1 100644 (file)
@@ -25,6 +25,8 @@
 #include "dimension-cache.hh"
 #include "grob-interface.hh"
 
+#include <set>
+
 class Grob
 {
 private:
@@ -171,6 +173,7 @@ Item *unsmob_item (SCM);
 /* refpoints */
 Grob *common_refpoint_of_list (SCM elt_list, Grob *, Axis a);
 Grob *common_refpoint_of_array (vector<Grob *> const &, Grob *, Axis a);
+Grob *common_refpoint_of_array (set<Grob *> const &, Grob *, Axis a);
 System *get_root_system (Grob *me);
 
 /* extents */
index 604d2fb4dfa706463d423fba58e94dc4db44fc70..1d02674814c7d9247249634ec0dc624eba31630e 100644 (file)
@@ -36,19 +36,12 @@ public:
   Skyline_pair (Box const &, Axis a);
 
   void raise (Real);
-  void grow (Real);
   void shift (Real);
   void deholify ();
-  Real smallest_shift (Skyline_pair const &other, Direction d,
-                       Real h_padding = 0, Real v_padding = 0);
-  Real left () const;
-  Real right () const;
-  bool intersects (Skyline_pair const &other) const;
   void insert (Box const &, Axis);
   void merge (Skyline_pair const &other);
   Skyline &operator [] (Direction d);
   Skyline const &operator [] (Direction d) const;
-  bool is_singleton () const;
   bool is_empty () const;
   void print () const;
   void print_points () const;
index a93316d93577779a92d7ccaee47520c2fcddd89c..eca597f8916a29b54184163507f9d818dd5ca543 100644 (file)
@@ -82,11 +82,7 @@ public:
   void print_points () const;
   void raise (Real);
   void shift (Real);
-  void invert ();
   Real distance (Skyline const &, Real horizon_padding = 0) const;
-  Real smallest_shift (Skyline const &, Direction d,
-                       Real horizon_padding = 0,
-                       Real vertical_padding = 0) const;
   Real touching_point (Skyline const &, Real horizon_padding = 0) const;
   Real shift_to_avoid (Skyline const &other, Real, Direction d, Real horizon_padding = 0);
   Real raise_to_avoid (Skyline const &other, Real, Direction d, Real horizon_padding = 0);
@@ -98,9 +94,6 @@ public:
   void set_minimum_height (Real height);
   void clear ();
   bool is_empty () const;
-  bool is_singleton () const;
-  Real left () const;
-  Real right () const;
   Skyline padded (Real horizon_padding) const;
 
   DECLARE_SCHEME_CALLBACK (get_touching_point, (SCM, SCM, SCM));
index 75104e44b9fb512de3b51482acefda7fcef25df7..5a0d16606c9faa6eecbd406b98641e061156f9b7 100644 (file)
 
 #include <cmath>                // ceil.
 #include <algorithm>
+#include <set>
 #include <map>
 
 using namespace std;
 
 #include "accidental-interface.hh"
+#include "accidental-placement.hh"
 #include "axis-group-interface.hh"
 #include "directional-element-interface.hh"
 #include "grob.hh"
@@ -80,6 +82,34 @@ finish_offset (Grob *me, Direction dir, Real total_off, Real *current_offset)
   return scm_from_double (total_off);
 }
 
+set<Grob *>
+get_support_set (Grob *me)
+{
+  // Only slightly kludgy heuristic...
+  // We want to make sure that all AccidentalPlacements'
+  // accidentals make it into the side support
+  extract_grob_set (me, "side-support-elements", proto_support);
+  set<Grob *> support;
+
+  for (vsize i = 0; i < proto_support.size (); i++)
+    {
+      if (Accidental_placement::has_interface (proto_support[i]))
+        {
+          Grob *accs = proto_support[i];
+          for (SCM acs = accs->get_object ("accidental-grobs"); scm_is_pair (acs);
+               acs = scm_cdr (acs))
+            for (SCM s = scm_cdar (acs); scm_is_pair (s); s = scm_cdr (s))
+              {
+                Grob *a = unsmob_grob (scm_car (s));
+                support.insert (a);
+              }
+        }
+      else
+        support.insert (proto_support[i]);
+    }
+  return support;
+}
+
 /* Put the element next to the support, optionally taking in
    account the extent of the support.
 
@@ -91,7 +121,7 @@ Side_position_interface::general_side_position (Grob *me, Axis a, bool use_exten
                                                 bool pure, int start, int end,
                                                 Real *current_offset)
 {
-  extract_grob_set (me, "side-support-elements", support);
+  set<Grob *> support = get_support_set (me);
 
   Grob *common = common_refpoint_of_array (support, me->get_parent (a), a);
   Grob *staff_symbol = Staff_symbol_referencer::get_staff_symbol (me);
@@ -114,9 +144,11 @@ Side_position_interface::general_side_position (Grob *me, Axis a, bool use_exten
 
   Direction dir = get_grob_direction (me);
 
-  for (vsize i = 0; i < support.size (); i++)
+  set<Grob *>::iterator it;
+
+  for (it = support.begin (); it != support.end (); it++)
     {
-      Grob *e = support[i];
+      Grob *e = *it;
 
       // In the case of a stem, we will find a note head as well
       // ignoring the stem solves cyclic dependencies if the stem is
@@ -166,7 +198,7 @@ Side_position_interface::skyline_side_position (Grob *me, Axis a,
                                                 bool pure, int start, int end,
                                                 Real *current_offset)
 {
-  extract_grob_set (me, "side-support-elements", support);
+  set<Grob *> support = get_support_set (me);
 
   Grob *common[2];
   for (Axis ax = X_AXIS; ax < NO_AXES; incr (ax))
@@ -210,10 +242,12 @@ Side_position_interface::skyline_side_position (Grob *me, Axis a,
   vector<Box> boxes;
   vector<Skyline_pair> skyps;
   Real min_h = dir == LEFT ? infinity_f : -infinity_f;
+  set<Grob *>::iterator it;
+
   map<Grob *, vector<Grob *> > note_column_map; // for parts of a note column
-  for (vsize i = 0; i < support.size (); i++)
+  for (it = support.begin (); it != support.end (); it++)
     {
-      Grob *e = support[i];
+      Grob *e = *it;
 
       // In the case of a stem, we will find a note head as well
       // ignoring the stem solves cyclic dependencies if the stem is
index 6175d1e27580655aca34bae9ec9d8acaebddbe3f..bbfe9234fcd9dbdc44eb3e33de244d3a61f85771 100644 (file)
@@ -76,52 +76,6 @@ Skyline_pair::insert (Box const &b, Axis a)
   skylines_[DOWN].insert (b, a);
 }
 
-Real
-Skyline_pair::left () const
-{
-  return min (skylines_[UP].left (), skylines_[DOWN].left ());
-}
-
-Real
-Skyline_pair::right () const
-{
-  return max (skylines_[UP].right (), skylines_[DOWN].right ());
-}
-
-// This function comes with the same caveats as smallest_shift:
-// if the skylines are not contiguous, we may report false
-// intersections.
-bool
-Skyline_pair::intersects (Skyline_pair const &other) const
-{
-  return skylines_[UP].distance (other[DOWN]) > 0
-         && other[UP].distance (skylines_[DOWN]) > 0;
-}
-
-Real
-Skyline_pair::smallest_shift (Skyline_pair const &other, Direction d,
-                              Real h_pad, Real v_pad)
-{
-  // If skylines_[UP] avoids other[DOWN] or skylines_[DOWN] avoids
-  // other[UP] then we will not intersect.
-  // Note that this is not guaranteed to return the smallest shift
-  // if one Skyline_pair is not connected: the smallest_shift left
-  // in the case of
-  // AAA
-  // BBBBBB
-  //    AAA
-  // will result in
-  //    AAA
-  // BBBBBB
-  //       AAA
-  // even though the originals did not collide.  If it becomes necessary,
-  // this case could be handled by splitting the Skyline_pairs up into
-  // their connected components.
-
-  return d * min (d * skylines_[UP].smallest_shift (other[DOWN], d, h_pad, v_pad),
-                  d * skylines_[DOWN].smallest_shift (other[UP], d, h_pad, v_pad));
-}
-
 void
 Skyline_pair::merge (Skyline_pair const &other)
 {
@@ -150,13 +104,6 @@ Skyline_pair::is_empty () const
          && skylines_[DOWN].is_empty ();
 }
 
-bool
-Skyline_pair::is_singleton () const
-{
-  return skylines_[UP].is_singleton ()
-         && skylines_[DOWN].is_singleton ();
-}
-
 Skyline &
 Skyline_pair::operator [] (Direction d)
 {
index 9bbd7e9752ec76ed93a3b9dec396a3e334297333..f062c00b6c512f59c11a2433c603310f1da3f973 100644 (file)
@@ -789,21 +789,6 @@ Skyline::internal_distance (Skyline const &other, Real *touch_point) const
   return dist;
 }
 
-// changes the direction that the skyline is pointing
-void
-Skyline::invert ()
-{
-  list<Building>::iterator i;
-  for (i = buildings_.begin (); i != buildings_.end (); i++)
-    if (!isinf (i->y_intercept_))
-      {
-        i->y_intercept_ *= -1;
-        i->slope_ *= -1;
-      }
-
-  sky_ = -sky_;
-}
-
 Real
 Skyline::height (Real airplane) const
 {
@@ -872,90 +857,6 @@ Skyline::to_points (Axis horizon_axis) const
   return out;
 }
 
-// Returns the smallest (non-negative) shift in the given
-// direction which will result in THIS and OTHER not overlapping.
-// Warning: this function is O(n^2 log n). Use sparingly.
-Real
-Skyline::smallest_shift (Skyline const &other,
-                         Direction d,
-                         Real horizon_padding,
-                         Real vertical_padding) const
-{
-  // If one or both of the paddings is zero, this can
-  // be optimized...
-  Skyline padded_me = padded (horizon_padding);
-  padded_me.raise (vertical_padding);
-
-  list<Building>::const_iterator i = padded_me.buildings_.begin ();
-  list<Building>::const_iterator j = other.buildings_.begin ();
-  list<Building>::const_iterator i_end = padded_me.buildings_.end ();
-  list<Building>::const_iterator j_end = other.buildings_.end ();
-
-  // Find all shifts that are not allowed.
-  vector<Interval> forbidden_shifts;
-  for (; i != i_end; ++i)
-    if (i->y_intercept_ != -infinity_f)
-      for (j = other.buildings_.begin (); j != j_end; ++j)
-        {
-          Interval iv = i->overlapping_shift_interval (*j);
-          if (!iv.is_empty ())
-            forbidden_shifts.push_back (iv);
-        }
-
-  // Now comes the trick: we want to find the smallest point
-  // that is not in the union of forbidden_shifts. We can represent
-  // the union of forbidden_shifts as a skyline, where a point is
-  // allowed if it has height -infinity_f and forbidden otherwise.
-  vector<Box> boxes;
-  for (vector<Interval>::iterator k = forbidden_shifts.begin ();
-       k != forbidden_shifts.end (); ++k)
-    boxes.push_back (Box (*k, Interval (-1, 0)));
-  Skyline s (boxes, X_AXIS, UP);
-
-  // Find the smallest (ie. closest to zero, in the appropriate direction)
-  // coordinate where the height of s is -infinity_f.
-  Real last_good_point = -infinity_f;
-  for (i = s.buildings_.begin (); i != s.buildings_.end (); ++i)
-    {
-      if (d == LEFT && i->start_ > 0)
-        return last_good_point;
-
-      if (i->y_intercept_ == -infinity_f)
-        {
-          if (i->start_ <= 0 && i->end_ >= 0)
-            return 0;
-          if (d == RIGHT && i->start_ >= 0)
-            return i->start_;
-
-          last_good_point = i->end_;
-        }
-    }
-
-  return infinity_f * d;
-}
-
-Real
-Skyline::left () const
-{
-  for (list<Building>::const_iterator i (buildings_.begin ());
-       i != buildings_.end (); i++)
-    if (i->y_intercept_ > -infinity_f)
-      return i->start_;
-
-  return infinity_f;
-}
-
-Real
-Skyline::right () const
-{
-  for (list<Building>::const_reverse_iterator i (buildings_.rbegin ());
-       i != buildings_.rend (); ++i)
-    if (i->y_intercept_ > -infinity_f)
-      return i->end_;
-
-  return -infinity_f;
-}
-
 bool
 Skyline::is_empty () const
 {
@@ -965,12 +866,6 @@ Skyline::is_empty () const
   return b.end_ == infinity_f && b.y_intercept_ == -infinity_f;
 }
 
-bool
-Skyline::is_singleton () const
-{
-  return buildings_.size () == 3;
-}
-
 void
 Skyline::clear ()
 {
index 4d2329032da616cd4dea626c141d26140f2a4601..47af14b0239aa174a9c4abca4ef305f25b5e28fc 100644 (file)
@@ -260,6 +260,7 @@ multiple voices on the same staff."
 
   \consists "Script_engraver"
   \consists "Script_column_engraver"
+  \consists "Fingering_column_engraver"
   \consists "Rhythmic_column_engraver"
   \consists "Note_spacing_engraver"
   \consists "Spanner_break_forbid_engraver"
index 8d9c457037538c4bddd95e8d44ecaad4ee1c6105..eb76e96e0b53e76bccc60a281543bb0013700f09 100644 (file)
@@ -215,6 +215,14 @@ accidentals)."
  "Note names."
  '())
 
+(ly:add-interface
+ 'octavate-eight-interface
+  "Interface that permits the nominal identification of the octavian
+annotation that multiplies by two the freqency of the pitches present
+in a given staff were they played on a clef that lacked said octavian
+annotation."
+  '())
+
 (ly:add-interface
  'only-prebreak-interface
  "Kill this grob after the line breaking process."
index 9da27ed7c1c97692b6c8131c6265f319f007ebf1..40218b3d2d6c72b6e8c38e5dbd82bd2151ec7330 100644 (file)
                                 inline-accidental-interface
                                 key-signature-interface
                                 note-head-interface
+                                octavate-eight-interface
                                 stem-interface
                                 time-signature-interface))
        (cross-staff . ,ly:beam::calc-cross-staff)
                                text-interface
                                text-script-interface))))))
 
+    (FingeringColumn
+     . (
+       (padding . 0.2)
+       (positioning-done . ,ly:fingering-column::calc-positioning-done)
+       (meta . ((class . Item)
+                (interfaces . (fingering-column-interface))))))
+
     (Flag
      . (
        (glyph-name . ,ly:flag::glyph-name)
        (Y-offset . ,ly:side-position-interface::y-aligned-side)
        (meta . ((class . Item)
                 (interfaces . (font-interface
+                               octavate-eight-interface
                                self-alignment-interface
                                side-position-interface
                                text-interface))))))