2 fingering-engraver.cc -- implement New_fingering_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2003 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"
34 note_event_
= finger_event_
= 0;
35 description_
= SCM_EOL
;
37 static int compare (Finger_tuple
const & c1
, Finger_tuple
const & c2
)
39 return c1
.position_
- c2
.position_
;
44 class New_fingering_engraver
: public Engraver
46 Array
<Finger_tuple
> fingerings_
;
47 Array
<Finger_tuple
> articulations_
;
48 Link_array
<Grob
> heads_
;
52 TRANSLATOR_DECLARATIONS(New_fingering_engraver
);
54 virtual void stop_translation_timestep ();
55 virtual void acknowledge_grob (Grob_info
);
56 void add_fingering (Grob
*, Music
*,Music
*);
57 void add_script (Grob
*, Music
*,Music
*);
58 void position_scripts();
62 New_fingering_engraver::acknowledge_grob (Grob_info inf
)
64 if (Rhythmic_head::has_interface (inf
.grob_
))
66 Music
* note_ev
=inf
.music_cause ();
68 SCM arts
= note_ev
->get_mus_property ("articulations");
70 for (SCM s
= arts
; gh_pair_p (s
); s
= gh_cdr (s
))
72 Music
* m
= unsmob_music (gh_car (s
));
78 if (m
->is_mus_type ("fingering-event"))
80 add_fingering (inf
.grob_
, m
, note_ev
);
82 else if (m
->is_mus_type ("script-event"))
84 add_script (inf
.grob_
, m
, note_ev
);
88 heads_
.push (inf
.grob_
);
90 else if (Stem::has_interface (inf
.grob_
))
96 extern Grob
*make_script_from_event (SCM
* descr
, Translator_group
*tg
, Music
* event
,
99 New_fingering_engraver::add_script (Grob
* head
,
105 ft
.script_
=make_script_from_event (&ft
.description_
, daddy_trans_
, event
, 0);
107 articulations_
.push (ft
);
108 announce_grob (ft
.script_
, event
->self_scm ());
111 ft
.script_
->set_parent (head
, X_AXIS
);
117 New_fingering_engraver::add_fingering (Grob
* head
,
123 ft
.script_
= new Item (get_property ("Fingering"));
124 announce_grob (ft
.script_
, event
->self_scm());
126 Side_position_interface::add_support (ft
.script_
, head
);
128 int d
= gh_scm2int ( event
->get_mus_property ("digit"));
133 Should add support for thumb. It's a little involved, since
134 the thumb lives in a different font. Maybe it should be moved?
141 music for the softenon children?
143 event
->origin()->warning (_("music for the martians."));
145 SCM sstr
= scm_number_to_string (gh_int2scm (d
), gh_int2scm (10)) ;
146 ft
.script_
->set_grob_property ("text", sstr
);
148 ft
.finger_event_
= event
;
149 ft
.note_event_
= hevent
;
152 fingerings_
.push (ft
);
156 New_fingering_engraver::position_scripts ()
160 This is not extremely elegant, but we have to do a little
161 formatting here, because the parent/child relations should be
162 known before we move on to the next time step.
164 A more sophisticated approach would be to set both X and Y parents
165 to the note head, and write a more flexible function for
166 positioning the fingerings, setting both X and Y coordinates.
168 for (int i
= 0; i
< fingerings_
.size(); i
++)
170 fingerings_
[i
].position_
= gh_scm2int (fingerings_
[i
].head_
-> get_grob_property( "staff-position"));
173 SCM fhd
= get_property ("fingerHorizontalDirection");
175 Array
<Finger_tuple
> up
, down
, horiz
;
176 for (int i
= fingerings_
.size(); i
--;)
178 SCM d
= fingerings_
[i
].finger_event_
->get_mus_property ("direction");
181 if (to_dir (d
) == UP
)
183 up
.push (fingerings_
[i
]);
186 down
.push (fingerings_
[i
]);
191 fingerings_
.sort (&Finger_tuple::compare
);
196 up
.push (fingerings_
.pop());
199 down
.push (fingerings_
[0]);
203 horiz
.concat (fingerings_
);
207 int center
= fingerings_
.size() / 2;
208 down
.concat (fingerings_
.slice (0,center
));
209 up
.concat (fingerings_
.slice (center
, fingerings_
.size()));
212 for (int i
= 0; i
< horiz
.size(); i
++)
214 Finger_tuple ft
= horiz
[i
];
215 Grob
* f
= ft
.script_
;
216 f
->set_parent (ft
.head_
, X_AXIS
);
217 f
->set_parent (ft
.head_
, Y_AXIS
);
218 f
->add_offset_callback (Self_alignment_interface::centered_on_parent_proc
, Y_AXIS
);
219 f
->add_offset_callback (Self_alignment_interface::aligned_on_self_proc
, Y_AXIS
);
220 f
->add_offset_callback (Side_position_interface::aligned_side_proc
, X_AXIS
);
222 f
->set_grob_property( "direction", fhd
);
226 int finger_prio
= 200;
227 for (int i
= 0; i
< up
.size(); i
++)
229 Finger_tuple ft
= up
[i
];
230 Grob
* f
= ft
.script_
;
231 f
->set_parent (ft
.head_
, X_AXIS
);
232 f
->set_grob_property ("script-priority",
233 gh_int2scm (finger_prio
+ i
));
234 f
->add_offset_callback (Side_position_interface::aligned_side_proc
, Y_AXIS
);
235 f
->add_offset_callback (Self_alignment_interface::centered_on_parent_proc
, X_AXIS
);
236 f
->add_offset_callback (Self_alignment_interface::aligned_on_self_proc
, X_AXIS
);
238 f
->set_grob_property ("direction", gh_int2scm (UP
));
240 Side_position_interface::add_staff_support (f
);
244 for (int i
= 0; i
< down
.size(); i
++)
246 Finger_tuple ft
= down
[i
];
247 Grob
* f
= ft
.script_
;
248 f
->set_parent (ft
.head_
, X_AXIS
);
249 f
->set_grob_property ("script-priority",
250 gh_int2scm (finger_prio
+ down
.size() - i
));
252 f
->add_offset_callback (Self_alignment_interface::centered_on_parent_proc
, X_AXIS
);
253 f
->add_offset_callback (Self_alignment_interface::aligned_on_self_proc
, X_AXIS
);
254 f
->add_offset_callback (Side_position_interface::aligned_side_proc
, Y_AXIS
);
255 f
->set_grob_property ("direction", gh_int2scm (DOWN
));
256 Side_position_interface::add_staff_support (f
);
262 New_fingering_engraver::stop_translation_timestep ()
264 if (fingerings_
.size ())
267 fingerings_
.clear ();
270 for (int i
= articulations_
.size(); i
--;)
272 Grob
*sc
= articulations_
[i
].script_
;
274 for (int j
= heads_
.size() ; j
--;)
275 Side_position_interface::add_support (sc
, heads_
[j
]);
277 if (stem_
&& to_dir (sc
->get_grob_property ("side-relative-direction")))
278 sc
->set_grob_property ("direction-source", stem_
->self_scm ());
280 SCM follow
= scm_assoc (ly_symbol2scm ("follow-into-staff"), articulations_
[i
].description_
);
281 if (gh_pair_p (follow
) && to_boolean (gh_cdr (follow
)))
282 sc
->add_offset_callback (Side_position_interface::quantised_position_proc
, Y_AXIS
);
284 Side_position_interface::add_staff_support (sc
);
290 articulations_
.clear();
294 New_fingering_engraver::New_fingering_engraver()
299 ENTER_DESCRIPTION(New_fingering_engraver
,
300 /* descr */ "Create fingering-scripts for notes in a New Chord.",
301 /* creats*/ "Fingering",
302 /* accepts */ "text-script-event",
303 /* acks */ "rhythmic-head-interface stem-interface",
304 /* reads */ "fingerHorizontalDirection",