source file of the GNU LilyPond music typesetter
- (c) 2002--2006 Juergen Reuter <reuter@ipd.uka.de>,
+ (c) 2002--2007 Juergen Reuter <reuter@ipd.uka.de>,
Pal Benko <benkop@freestart.hu>
*/
#include "font-interface.hh"
#include "international.hh"
#include "mensural-ligature.hh"
-#include "music.hh"
#include "note-column.hh"
#include "note-head.hh"
#include "output-def.hh"
#include "paper-column.hh"
+#include "pitch.hh"
#include "rhythmic-head.hh"
#include "spanner.hh"
#include "staff-symbol-referencer.hh"
+#include "stream-event.hh"
#include "warn.hh"
+#include "translator.icc"
+
/*
* TODO: accidentals are aligned with the first note;
* they must appear ahead.
* TODO: prohibit ligatures having notes differing only in accidentals
* (like \[ a\breve g as \])
*
- * TODO: dotted heads: avoid next note colliding with the dot, e.g. by
- * putting it *above* (rather than after) the affected ligature head.
- *
* TODO: do something with multiple voices within a ligature. See
* for example:
* Ockeghem: Missa Ecce ancilla domini, bassus part, end of Christe.
protected:
virtual Spanner *create_ligature_spanner ();
- virtual void build_ligature (Spanner *ligature, std::vector<Grob_info> primitives);
-
+ virtual void build_ligature (Spanner *ligature, vector<Grob_info> primitives);
+ DECLARE_TRANSLATOR_LISTENER (ligature);
+
public:
TRANSLATOR_DECLARATIONS (Mensural_ligature_engraver);
private:
- void transform_heads (std::vector<Grob_info> primitives);
- void propagate_properties (Spanner *ligature, std::vector<Grob_info> primitives);
- void fold_up_primitives (std::vector<Grob_info> primitives);
+ void transform_heads (vector<Grob_info> primitives);
+ void propagate_properties (Spanner *ligature, vector<Grob_info> primitives);
+ void fold_up_primitives (vector<Grob_info> primitives);
};
+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 ()
{
brew_ligature_primitive_proc =
}
void
-Mensural_ligature_engraver::transform_heads (std::vector<Grob_info> primitives)
+Mensural_ligature_engraver::transform_heads (vector<Grob_info> primitives)
{
if (primitives.size () < 2)
{
{
Grob_info info = primitives[i];
Item *primitive = dynamic_cast<Item *> (info.grob ());
- int duration_log = Note_head::get_balltype (primitive);
+ int duration_log = Rhythmic_head::duration_log (primitive);
- Music *nr = info.music_cause ();
+ Stream_event *nr = info.event_cause ();
/*
ugh. why not simply check for pitch?
*/
- if (!nr->is_mus_type ("note-event"))
+ if (!nr->in_event_class ("note-event"))
{
nr->origin ()->warning
(_f ("cannot determine pitch of ligature primitive -> skipping"));
}
// b. descendens longa or brevis
else if (i < s - 1
- && (unsmob_pitch (primitives[i + 1].music_cause ()
+ && (unsmob_pitch (primitives[i + 1].event_cause ()
->get_property ("pitch"))->steps () < pitch)
&& duration_log > -3)
{
*/
void
Mensural_ligature_engraver::propagate_properties (Spanner *ligature,
- std::vector<Grob_info> primitives)
+ vector<Grob_info> primitives)
{
Real thickness
= robust_scm2double (ligature->get_property ("thickness"), 1.4);
thickness
- *= ligature->layout ()->get_dimension (ly_symbol2scm ("linethickness"));
+ *= ligature->layout ()->get_dimension (ly_symbol2scm ("line-thickness"));
Real head_width
= Font_interface::get_default_font (ligature)->
}
void
-Mensural_ligature_engraver::fold_up_primitives (std::vector<Grob_info> primitives)
+Mensural_ligature_engraver::fold_up_primitives (vector<Grob_info> primitives)
{
Item *first = 0;
- Real distance = 0;
+ Real distance = 0.0;
+ Real dot_shift = 0.0;
for (vsize i = 0; i < primitives.size (); i++)
{
Item *current = dynamic_cast<Item *> (primitives[i].grob ());
if (i == 0)
- first = current;
-
- get_set_column (current, first->get_column ());
+ {
+ first = current;
+ dot_shift = 1.5 * Staff_symbol_referencer::staff_space (first);
+ }
- if (i > 0)
- current->translate_axis (distance, X_AXIS);
+ move_related_items_to_column (current, first->get_column (),
+ distance);
distance
+= scm_to_double (current->get_property ("head-width"))
- scm_to_double (current->get_property ("thickness"));
+
+ if (Rhythmic_head::dot_count (current) > 0)
+ // Move dots above/behind the ligature.
+ {
+ if (i + 1 < primitives.size ())
+ // dot in the midst => move above head
+ {
+ // FIXME: Amount of vertical dot-shift should depend on
+ // pitch.
+ //
+ // FIXME: dot placement is horizontally slightly off.
+ Rhythmic_head::get_dots (current)->translate_axis (dot_shift, Y_AXIS);
+ }
+ else
+ // trailing dot => move behind head
+ {
+ double head_width =
+ scm_to_double (current->get_property ("head-width"));
+ Rhythmic_head::get_dots (current)->
+ translate_axis (head_width, X_AXIS);
+ }
+ }
}
}
void
Mensural_ligature_engraver::build_ligature (Spanner *ligature,
- std::vector<Grob_info> primitives)
+ vector<Grob_info> primitives)
{
transform_heads (primitives);
propagate_properties (ligature, primitives);
fold_up_primitives (primitives);
}
-#include "translator.icc"
-
ADD_ACKNOWLEDGER (Mensural_ligature_engraver, rest);
ADD_ACKNOWLEDGER (Mensural_ligature_engraver, note_head);
+
ADD_TRANSLATOR (Mensural_ligature_engraver,
/* doc */ "Handles Mensural_ligature_events by glueing special ligature heads together.",
/* create */ "MensuralLigature",
- /* accept */ "ligature-event",
/* read */ "",
/* write */ "");