]> git.donarmstrong.com Git - lilypond.git/commitdiff
Fix #189: Episema over single neume.
authorNeil Puttock <n.puttock@gmail.com>
Tue, 2 Mar 2010 20:20:39 +0000 (20:20 +0000)
committerNeil Puttock <n.puttock@gmail.com>
Tue, 2 Mar 2010 20:20:39 +0000 (20:20 +0000)
* add Episema_engraver (based on Text_spanner_engraver) which listens to
  EpisemaEvent and creates Episema spanner

* set NoteHeads as 'side-support-elements so spanner can be quantized over
  neume/melisma

* ensure episema doesn't extend past bound items by setting NoteColumns
  as spanner bounds

* add regression test

12 files changed:
Documentation/notation/ancient.itely
input/regression/display-lily-tests.ly
input/regression/episema.ly [new file with mode: 0644]
lily/episema-engraver.cc [new file with mode: 0644]
ly/engraver-init.ly
ly/gregorian.ly
ly/spanners-init.ly
scm/define-event-classes.scm
scm/define-grob-interfaces.scm
scm/define-grobs.scm
scm/define-music-display-methods.scm
scm/define-music-types.scm

index adec460f29e650f651a884b4f99a20c3ddc1a124..96671041ed09df10358069feca15ae3a19182f00 100644 (file)
@@ -1302,18 +1302,26 @@ Vaticana} style are provided.
     \override TextScript #'font-family = #'typewriter
     \override TextScript #'font-shape = #'upright
     \override Script #'padding = #-0.1
-    a\ictus_"ictus " \break
-    a\circulus_"circulus " \break
-    a\semicirculus_"semicirculus " \break
-    a\accentus_"accentus " \break
+    a\ictus_"ictus " \bar "" \break
+    a\circulus_"circulus " \bar "" \break
+    a\semicirculus_"semicirculus " \bar "" \break
+    a\accentus_"accentus " \bar "" \break
     \[ a_"episema" \episemInitium \pes b \flexa a b \episemFinis \flexa a \]
   }
 }
 @end lilypond
 
 
-@c @seealso
-@c TODO: nothing here yet ...
+Snippets:
+@rlsr{Ancient notation}.
+
+Internals Reference:
+@rinternals{Episema},
+@rinternals{EpisemaEvent},
+@rinternals{Episema_engraver},
+@rinternals{Script},
+@rinternals{ScriptEvent},
+@rinternals{Script_engraver}.
 
 
 @knownissues
@@ -1321,9 +1329,6 @@ Vaticana} style are provided.
 Some articulations are vertically placed too closely to the
 corresponding note heads.
 
-The episema line is not displayed in many cases.  If it is displayed,
-the right end of the episema line is often too far to the right.
-
 
 @c {{{2Augmentum dots (@emph{morae})
 @node Augmentum dots (@emph{morae})
index 7d81a696afaf4b7f401567ddcbad281c9dcfb538..5c128d1654069320671195ad608ba7649dbdcbb7 100644 (file)
@@ -132,6 +132,7 @@ stderr of this run."
 \test "" ##[ { c(  c)  c^(  c^)  c_(  c_)  } #]        % SlurEvent
 \test "" ##[ { c\<  c\!  c^\<  c^\!  c_\<  c_\!  } #]  % CrescendoEvent
 \test "" ##[ { c\>  c\!  c^\>  c^\!  c_\>  c_\!  } #]  % DecrescendoEvent
+\test "" ##[ { c\episemInitium  c\episemFinis  } #] % EpisemaEvent
 \test "" ##[ { c\(  c\)  c^\(  c^\)  c_\(  c_\)  } #]  % PhrasingSlurEvent
 \test "" ##[ { c\sustainOn  c\sustainOff  } #] % SustainEvent
 \test "" ##[ { c\sostenutoOn  c\sostenutoOff  } #] % SostenutoEvent
diff --git a/input/regression/episema.ly b/input/regression/episema.ly
new file mode 100644 (file)
index 0000000..44ccae2
--- /dev/null
@@ -0,0 +1,16 @@
+\version "2.13.15"
+
+\header {
+  texidoc = "An episema can be typeset over a single neume or a
+melisma.  Its position is quantized between staff lines."
+}
+
+#(set-global-staff-size 26)
+\include "gregorian.ly"
+
+\new VaticanaVoice {
+  \revert Score.SpacingSpanner #'packed-spacing
+  a\episemInitium\episemFinis
+  \[ a\episemInitium \pes b \flexa a\episemFinis \]
+  \[ a\episemInitium \pes b \flexa a b\episemFinis \flexa a \]
+}
diff --git a/lily/episema-engraver.cc b/lily/episema-engraver.cc
new file mode 100644 (file)
index 0000000..a24640f
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+  This file is part of LilyPond, the GNU music typesetter.
+
+  Copyright (C) 2010 Neil Puttock <n.puttock@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 "engraver.hh"
+#include "international.hh"
+#include "note-column.hh"
+#include "pointer-group-interface.hh"
+#include "side-position-interface.hh"
+#include "spanner.hh"
+#include "stream-event.hh"
+
+#include "translator.icc"
+
+class Episema_engraver : public Engraver
+{
+public:
+  TRANSLATOR_DECLARATIONS (Episema_engraver);
+protected:
+  virtual void finalize ();
+  DECLARE_TRANSLATOR_LISTENER (episema);
+  DECLARE_ACKNOWLEDGER (note_column);
+  DECLARE_ACKNOWLEDGER (note_head);
+  void stop_translation_timestep ();
+  void process_music ();
+
+private:
+  Spanner *span_;
+  Spanner *finished_;
+  Stream_event *current_event_;
+  Drul_array<Stream_event *> event_drul_;
+  vector<Grob *> note_columns_;
+  void typeset_all ();
+};
+
+Episema_engraver::Episema_engraver ()
+{
+  finished_ = 0;
+  current_event_ = 0;
+  span_ = 0;
+  event_drul_.set (0, 0);
+}
+
+IMPLEMENT_TRANSLATOR_LISTENER (Episema_engraver, episema);
+void
+Episema_engraver::listen_episema (Stream_event *ev)
+{
+  Direction d = to_dir (ev->get_property ("span-direction"));
+  // Must not ASSIGN_EVENT_ONCE here, since episema
+  // can be typeset over a single neume
+  event_drul_[d] = ev;
+}
+
+void
+Episema_engraver::process_music ()
+{
+  if (event_drul_[START])
+    {
+      if (current_event_)
+       event_drul_[START]->origin ()->warning (_ ("already have an episema"));
+      else
+       {
+         current_event_ = event_drul_[START];
+         span_ = make_spanner ("Episema", event_drul_[START]->self_scm ());
+
+         event_drul_[START] = 0;
+       }
+    }
+  if (event_drul_[STOP])
+    {
+      if (!span_)
+       event_drul_[STOP]
+         ->origin ()->warning (_ ("cannot find start of episema"));
+      else
+       {
+         finished_ = span_;
+         announce_end_grob (finished_, SCM_EOL);
+         span_ = 0;
+         current_event_ = 0;
+         note_columns_.clear ();
+       }
+    }
+}
+
+void
+Episema_engraver::typeset_all ()
+{
+  if (finished_)
+    {
+      if (!finished_->get_bound (RIGHT))
+       {
+         Grob *col = (note_columns_.size ()
+                      ? note_columns_.back ()
+                      : unsmob_grob (get_property ("currentMusicalColumn")));
+         finished_->set_bound (RIGHT, col);
+       }
+      finished_ = 0;
+    }
+}
+
+void
+Episema_engraver::stop_translation_timestep ()
+{
+  if (span_ && !span_->get_bound (LEFT))
+    {
+      Grob *col = (note_columns_.size ()
+                  ? note_columns_.front ()
+                  : unsmob_grob (get_property ("currentMusicalColumn")));
+      span_->set_bound (LEFT, col);
+    }
+
+  typeset_all ();
+  event_drul_.set (0, 0);
+}
+
+void
+Episema_engraver::finalize ()
+{
+  typeset_all ();
+  if (span_)
+    {
+      current_event_->origin ()->warning (_ ("unterminated episema"));
+      span_->suicide ();
+      span_ = 0;
+    }
+}
+
+void
+Episema_engraver::acknowledge_note_column (Grob_info info)
+{
+  note_columns_.push_back (info.grob ());
+}
+
+void
+Episema_engraver::acknowledge_note_head (Grob_info info)
+{
+  if (span_)
+    {
+      Side_position_interface::add_support (span_, info.grob ());
+      add_bound_item (span_, info.grob ());
+    }
+  else if (finished_)
+    {
+      Side_position_interface::add_support (finished_, info.grob ());
+      add_bound_item (finished_, info.grob ());
+    }
+}
+
+ADD_ACKNOWLEDGER (Episema_engraver, note_column);
+ADD_ACKNOWLEDGER (Episema_engraver, note_head);
+
+ADD_TRANSLATOR (Episema_engraver,
+               /* doc */
+               "Create an @emph{Editio Vaticana}-style episema line.",
+
+               /* create */
+               "Episema ",
+
+               /* read */
+               "",
+
+               /* write */
+               ""
+               );
index b4f023e50023ac010d13936bff7183fd01630f43..6d4b656dd7e0cb68a21d1a1f84e41cb84f77ce2c 100644 (file)
@@ -825,6 +825,8 @@ of Editio Vaticana."
   \remove "Stem_engraver"
   \remove "Ligature_bracket_engraver"
   \consists "Vaticana_ligature_engraver"
+  \remove "Text_spanner_engraver"
+  \consists "Episema_engraver"
 
   %% Set default head for notes outside of \[ \].
   \override NoteHead #'style = #'vaticana.punctum
@@ -835,15 +837,6 @@ of Editio Vaticana."
 
   %% There are no beams in Gregorian Chant notation.
   autoBeaming = ##f
-
-  %% Prepare TextSpanner for \episem{Initium|Finis} use.
-  %%
-  %% FIXME: The line @code{\override TextSpanner #'padding = #-0.1} is
-  %% required to force the articulation signs being placed vertically
-  %% tightly to the correpsonding note heads.
-  %%
-  \override TextSpanner #'style = #'line
-  \override TextSpanner #'padding = #-0.1
 }
 
 \context {
@@ -892,6 +885,7 @@ of Editio Vaticana."
   \Voice
   \name "GregorianTranscriptionVoice"
   \alias "Voice"
+  \consists "Episema_engraver"
 
   %% Removing ligature bracket engraver without replacing it by some
   %% other ligature engraver would cause a "Junking event: `LigatureEvent'"
@@ -906,18 +900,6 @@ of Editio Vaticana."
   %% There are no beams in Gregorian Chant notation.
   autoBeaming = ##f
 
-  %% Prepare TextSpanner for \episem{Initium|Finis} use.
-  %%
-  %% N.B.: dash-fraction MUST be unset; otherwise, TextSpanner will
-  %% always produce dashed lines, regardless of the style property.
-  %%
-  %% FIXME: The line @code{\override TextSpanner #'padding = #-0.1} is
-  %% required to force the articulation signs being placed vertically
-  %% tightly to the correpsonding note heads.
-  %%
-  \override TextSpanner #'dash-fraction = #'()
-  \override TextSpanner #'style = #'line
-  \override TextSpanner #'padding = #-0.1
 }
 
 \context {
index d8fc1aac7bb8638362b883589e236775692a585d..367dbbf16b62d8e323b3c50df749c95bf38e2a2d 100644 (file)
@@ -149,8 +149,6 @@ accentus = #(make-articulation "accentus")
 ictus = #(make-articulation "ictus")
 semicirculus = #(make-articulation "semicirculus")
 circulus = #(make-articulation "circulus")
-episemInitium = \startTextSpan
-episemFinis = \stopTextSpan
 
 %
 % \augmentum increases the dot-count value of all note heads to which
@@ -224,7 +222,7 @@ ligature = #(define-music-function
 \layout {
     indent = 0.0
 
-    %%% TODO: should raggedright be the default?
+    %%% TODO: should ragged-right be the default?
     %ragged-right = ##t
     ragged-last = ##t
 
index 7b26094e497fbbfdf81c6b5fe20cc271644344c0..afcfaf445f986d6fcced66c81d4bab8e5057be86 100644 (file)
@@ -18,6 +18,10 @@ startTrillSpan = #(make-span-event 'TrillSpanEvent START)
 stopTrillSpan = #(make-span-event 'TrillSpanEvent STOP)
 
 
+episemInitium = #(make-span-event 'EpisemaEvent START)
+episemFinis = #(make-span-event 'EpisemaEvent STOP)
+
+
 % STOP: junkme!
 cresc =  {
   #(ly:export (make-event-chord (list cr)))
index eb69eaf8e2deeb3c2cf664d0e078b845206e7ced..70387c8c26918ec7b55deaa7e74eb385b559b6e4 100644 (file)
@@ -41,7 +41,7 @@
     (part-combine-event . (solo-one-event solo-two-event unisono-event))
     (break-event . (line-break-event page-break-event page-turn-event))
     (dynamic-event . (absolute-dynamic-event))
-    (span-event . (span-dynamic-event beam-event ligature-event
+    (span-event . (span-dynamic-event beam-event episema-event ligature-event
                         pedal-event phrasing-slur-event slur-event staff-span-event
                         text-span-event trill-span-event tremolo-span-event 
                         tuplet-span-event))
index 96d3bd7d971d34235f1d638399a394f7c94a78ff..b73506790db88b41e6a0ba2f226506b7ef0a17de 100644 (file)
@@ -66,6 +66,11 @@ note)."
  "Dynamic text spanner."
  '(text))
 
+(ly:add-interface
+ 'episema-interface
+ "An episema line."
+ '())
+
 (ly:add-interface
  'finger-interface
  "A fingering instruction."
index b1cfb63becec318a08b5f48732e75e193c800f04..efd310c1daaf6bf985e2b7dae363fd6a1822cd6a 100644 (file)
                                text-interface))))))
 
 
+    (Episema
+     . (
+       (bound-details . ((left . ((Y . 0)
+                                  (padding . 0)
+                                  (attach-dir . ,LEFT)
+                                  ))
+                         (right . ((Y . 0)
+                                   (padding . 0)
+                                   (attach-dir . ,RIGHT)
+                                   ))
+                         ))
+       (direction . ,UP)
+       (left-bound-info . ,ly:line-spanner::calc-left-bound-info)
+       (quantize-position . #t)
+       (right-bound-info . ,ly:line-spanner::calc-right-bound-info)
+       (side-axis . ,Y)
+       (stencil . ,ly:line-spanner::print)
+       (style . line)
+       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (meta . ((class . Spanner)
+                (interfaces . (episema-interface
+                               font-interface
+                               line-interface
+                               line-spanner-interface
+                               side-position-interface))))))
+
+
     (Fingering
      . (
 
index 3254a90469b53788ab81f6ed0ca2b60fab9765d6..469c65408adfa3da55ba4713c16499761d9e992d 100644 (file)
     'BeamForbidEvent
     'CrescendoEvent
     'DecrescendoEvent
+    'EpisemaEvent
     'ExtenderEvent
     'FingeringEvent
     'GlissandoEvent
 (define-span-event-display-method SlurEvent (event parser) #f "(" ")")
 (define-span-event-display-method CrescendoEvent (event parser) #f "\\<" "\\!")
 (define-span-event-display-method DecrescendoEvent (event parser) #f "\\>" "\\!")
+(define-span-event-display-method EpisemaEvent (event parser) #f "\\episemInitium" "\\episemFinis")
 (define-span-event-display-method PhrasingSlurEvent (event parser) #f "\\(" "\\)")
 (define-span-event-display-method SustainEvent (event parser) #f "\\sustainOn" "\\sustainOff")
 (define-span-event-display-method SostenutoEvent (event parser) #f "\\sostenutoOn" "\\sostenutoOff")
index 973e59a403872076ee125ec3505f82899d9c32ad..356ba898a98006489fb9ac367ba0b8074b6aa913 100644 (file)
@@ -177,6 +177,11 @@ An alternative syntax is @var{note}@code{\\decr} @dots{}
                  event))
        ))
 
+    (EpisemaEvent
+     . ((description . "Begin or end an episema.")
+       (types . (general-music span-event event episema-event))
+       ))
+
     (Event
      . ((description . "Atomic music event.")
        (types . (general-music event))