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 Array
<Finger_tuple
> up
, down
, horiz
;
174 for (int i
= fingerings_
.size(); i
--;)
176 SCM d
= fingerings_
[i
].finger_event_
->get_mus_property ("direction");
179 if (to_dir (d
) == UP
)
181 up
.push (fingerings_
[i
]);
184 down
.push (fingerings_
[i
]);
189 fingerings_
.sort (&Finger_tuple::compare
);
190 SCM fhd
= get_property ("fingerHorizontalDirection");
194 up
.push (fingerings_
.pop());
195 down
.push (fingerings_
[0]);
202 int center
= fingerings_
.size() / 2;
203 down
.concat (fingerings_
.slice (0,center
));
204 up
.concat (fingerings_
.slice (center
, fingerings_
.size()));
207 for (int i
= 0; i
< horiz
.size(); i
++)
209 Finger_tuple ft
= horiz
[i
];
210 Grob
* f
= ft
.script_
;
211 f
->set_parent (ft
.head_
, X_AXIS
);
212 f
->set_parent (ft
.head_
, Y_AXIS
);
213 f
->add_offset_callback (Self_alignment_interface::centered_on_parent_proc
, Y_AXIS
);
214 f
->add_offset_callback (Self_alignment_interface::aligned_on_self_proc
, Y_AXIS
);
215 f
->add_offset_callback (Side_position_interface::aligned_side_proc
, X_AXIS
);
217 f
->set_grob_property( "direction", fhd
);
221 int finger_prio
= 200;
222 for (int i
= 0; i
< up
.size(); i
++)
224 Finger_tuple ft
= up
[i
];
225 Grob
* f
= ft
.script_
;
226 f
->set_parent (ft
.head_
, X_AXIS
);
227 f
->set_grob_property ("script-priority",
228 gh_int2scm (finger_prio
+ i
));
229 f
->add_offset_callback (Side_position_interface::aligned_side_proc
, Y_AXIS
);
230 f
->add_offset_callback (Self_alignment_interface::centered_on_parent_proc
, X_AXIS
);
231 f
->add_offset_callback (Self_alignment_interface::aligned_on_self_proc
, X_AXIS
);
233 f
->set_grob_property ("direction", gh_int2scm (UP
));
235 Side_position_interface::add_staff_support (f
);
239 for (int i
= 0; i
< down
.size(); i
++)
241 Finger_tuple ft
= down
[i
];
242 Grob
* f
= ft
.script_
;
243 f
->set_parent (ft
.head_
, X_AXIS
);
244 f
->set_grob_property ("script-priority",
245 gh_int2scm (finger_prio
+ down
.size() - i
));
247 f
->add_offset_callback (Self_alignment_interface::centered_on_parent_proc
, X_AXIS
);
248 f
->add_offset_callback (Self_alignment_interface::aligned_on_self_proc
, X_AXIS
);
249 f
->add_offset_callback (Side_position_interface::aligned_side_proc
, Y_AXIS
);
250 f
->set_grob_property ("direction", gh_int2scm (DOWN
));
251 Side_position_interface::add_staff_support (f
);
257 New_fingering_engraver::stop_translation_timestep ()
259 if (fingerings_
.size ())
262 fingerings_
.clear ();
265 for (int i
= articulations_
.size(); i
--;)
267 Grob
*sc
= articulations_
[i
].script_
;
269 for (int j
= heads_
.size() ; j
--;)
270 Side_position_interface::add_support (sc
, heads_
[j
]);
272 if (stem_
&& to_dir (sc
->get_grob_property ("side-relative-direction")))
273 sc
->set_grob_property ("direction-source", stem_
->self_scm ());
275 SCM follow
= scm_assoc (ly_symbol2scm ("follow-into-staff"), articulations_
[i
].description_
);
276 if (gh_pair_p (follow
) && to_boolean (gh_cdr (follow
)))
277 sc
->add_offset_callback (Side_position_interface::quantised_position_proc
, Y_AXIS
);
279 Side_position_interface::add_staff_support (sc
);
285 articulations_
.clear();
289 New_fingering_engraver::New_fingering_engraver()
294 ENTER_DESCRIPTION(New_fingering_engraver
,
295 /* descr */ "Create fingering-scripts for notes in a New Chord.",
296 /* creats*/ "Fingering",
297 /* accepts */ "text-script-event",
298 /* acks */ "rhythmic-head-interface stem-interface",
299 /* reads */ "fingerHorizontalDirection",