2 fingering-engraver.cc -- implement New_fingering_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
11 #include "engraver.hh"
12 #include "side-position-interface.hh"
16 #include "rhythmic-head.hh"
17 #include "self-alignment-interface.hh"
29 static int compare (Finger_tuple const & c1, Finger_tuple const & c2)
31 return c1.position_- c2.position_;
36 class New_fingering_engraver : public Engraver
38 Array<Finger_tuple> fingerings_;
40 TRANSLATOR_DECLARATIONS(New_fingering_engraver);
42 virtual void stop_translation_timestep ();
43 virtual void acknowledge_grob (Grob_info);
44 void add_fingering (Grob*, Music*,Music*);
45 void position_scripts();
49 New_fingering_engraver::acknowledge_grob (Grob_info inf)
51 if (Rhythmic_head::has_interface (inf.grob_))
53 Music * note_ev =inf.music_cause ();
55 SCM arts = note_ev->get_mus_property ("articulations");
57 for (SCM s = arts; gh_pair_p (s); s = gh_cdr (s))
59 Music * m = unsmob_music (gh_car (s));
61 if (m && m->is_mus_type ("fingering-event"))
63 add_fingering (inf.grob_ , m, note_ev);
71 New_fingering_engraver::add_fingering (Grob * head,
77 ft.fingering_ = new Item (get_property ("Fingering"));
78 announce_grob (ft.fingering_, event->self_scm());
80 Side_position_interface::add_support (ft.fingering_, head);
82 int d = gh_scm2int ( event->get_mus_property ("digit"));
87 Should add support for thumb. It's a little involved, since
88 the thumb lives in a different font. Maybe it should be moved?
95 music for the softenon children?
97 event->origin()->warning (_("music for the martians."));
99 SCM sstr = scm_number_to_string (gh_int2scm (d), gh_int2scm (10)) ;
100 ft.fingering_->set_grob_property ("text", sstr);
102 ft.finger_event_ = event;
103 ft.note_event_ = hevent;
106 fingerings_.push (ft);
110 New_fingering_engraver::position_scripts ()
114 This is not extremely elegant, but we have to do a little
115 formatting here, because the parent/child relations should be
116 known before we move on to the next time step.
118 A more sophisticated approach would be to set both X and Y parents
119 to the note head, and write a more flexible function for
120 positioning the fingerings, setting both X and Y coordinates.
124 for (int i = 0; i < fingerings_.size(); i++)
126 fingerings_[i].position_ = gh_scm2int (fingerings_[i].head_ -> get_grob_property( "staff-position"));
131 Array<Finger_tuple> up, down, horiz;
133 for (int i = fingerings_.size(); i--;)
135 SCM d = fingerings_[i].finger_event_->get_mus_property ("direction");
138 if (to_dir (d) == UP)
140 up.push (fingerings_[i]);
143 down.push (fingerings_[i]);
148 fingerings_.sort (&Finger_tuple::compare);
149 if (to_boolean (get_property ("fingersHorizontal")))
151 up.push (fingerings_.pop());
152 down.push (fingerings_[0]);
159 int center = fingerings_.size() / 2;
160 down.concat (fingerings_.slice (0,center));
161 up.concat (fingerings_.slice (center, fingerings_.size()));
164 for (int i = 0; i < horiz.size(); i++)
166 Finger_tuple ft = horiz[i];
167 Grob* f = ft.fingering_;
168 f->set_parent (ft.head_, X_AXIS);
169 f->set_parent (ft.head_, Y_AXIS);
170 f->add_offset_callback (Self_alignment_interface::centered_on_parent_proc, Y_AXIS);
171 f->add_offset_callback (Self_alignment_interface::aligned_on_self_proc, Y_AXIS);
172 f->add_offset_callback (Side_position_interface::aligned_side_proc, X_AXIS);
173 f->set_grob_property( "direction", gh_int2scm (RIGHT));
177 int finger_prio = 200;
178 for (int i = 0; i < up.size(); i++)
180 Finger_tuple ft = up[i];
181 Grob* f = ft.fingering_;
182 f->set_parent (ft.head_, X_AXIS);
183 f->set_grob_property ("script-priority",
184 gh_int2scm (finger_prio + i));
185 f->add_offset_callback (Side_position_interface::aligned_side_proc, Y_AXIS);
186 f->add_offset_callback (Self_alignment_interface::centered_on_parent_proc, X_AXIS);
187 f->add_offset_callback (Self_alignment_interface::aligned_on_self_proc, X_AXIS);
189 f->set_grob_property ("direction", gh_int2scm (UP));
191 Side_position_interface::add_staff_support (f);
195 for (int i = 0; i < down.size(); i++)
197 Finger_tuple ft = down[i];
198 Grob* f = ft.fingering_;
199 f->set_parent (ft.head_, X_AXIS);
200 f->set_grob_property ("script-priority",
201 gh_int2scm (finger_prio + down.size() - i));
203 f->add_offset_callback (Self_alignment_interface::centered_on_parent_proc, X_AXIS);
204 f->add_offset_callback (Self_alignment_interface::aligned_on_self_proc, X_AXIS);
205 f->add_offset_callback (Side_position_interface::aligned_side_proc, Y_AXIS);
206 f->set_grob_property ("direction", gh_int2scm (DOWN));
207 Side_position_interface::add_staff_support (f);
213 New_fingering_engraver::stop_translation_timestep ()
215 if (!fingerings_.size ())
219 fingerings_.clear ();
223 New_fingering_engraver::New_fingering_engraver()
228 ENTER_DESCRIPTION(New_fingering_engraver,
229 /* descr */ "Create fingering-scripts for notes in a New Chord.",
230 /* creats*/ "Fingering",
231 /* accepts */ "text-script-event",
232 /* acks */ "rhythmic-head-interface stem-interface",
233 /* reads */ "fingersHorizontal",