2 script-engraver.cc -- implement Script_engraver
4 (c) 1997--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 #include "side-position-interface.hh"
11 #include "rhythmic-head.hh"
12 #include "engraver.hh"
13 #include "note-column.hh"
27 description_
= SCM_EOL
;
31 class Script_engraver
: public Engraver
33 Array
<Script_tuple
> scripts_
;
35 TRANSLATOR_DECLARATIONS (Script_engraver
);
37 virtual bool try_music (Music
*);
38 virtual void stop_translation_timestep ();
39 virtual void process_music ();
40 virtual void acknowledge_grob (Grob_info
);
44 Script_engraver::try_music (Music
*r
)
46 if (r
->is_mus_type ("articulation-event"))
49 Discard double articulations.
50 This is necessary for part-combining.
52 for (int j
= 0; j
< scripts_
.size (); j
++)
53 if (ly_c_equal_p (scripts_
[j
]. event_
->get_property ("articulation-type"),
54 r
->get_property ("articulation-type")
68 copy_property (Grob
* g
, SCM sym
, SCM alist
)
70 if (g
->internal_get_property (sym
) == SCM_EOL
)
72 SCM entry
= scm_assoc (sym
,alist
);
73 if (ly_c_pair_p (entry
))
75 g
->internal_set_property (sym
, ly_cdr (entry
));
82 We add the properties, one by one for each Script. We could save a
83 little space by tacking the props onto the Script grob (i.e. make
84 ScriptStaccato , ScriptMarcato, etc. )
86 void make_script_from_event (Grob
*p
,
87 SCM
* descr
, Context
*tg
,
91 SCM alist
= tg
->get_property ("scriptDefinitions");
92 SCM art
= scm_assoc (art_type
, alist
);
94 if (art
== SCM_BOOL_F
)
96 warning (_("Don't know how to interpret articulation:"));
97 warning (_("Scheme encoding: "));
98 scm_write (art_type
, scm_current_error_port ());
107 copy_property (p
, ly_symbol2scm ("script-stencil"), art
);
108 copy_property (p
, ly_symbol2scm ("direction"), art
);
109 copy_property (p
, ly_symbol2scm ("side-relative-direction"), art
);
112 SCM sprio
= scm_assoc (ly_symbol2scm ("script-priority"), art
);
113 if (ly_c_pair_p (sprio
))
114 prio
= ly_scm2int (ly_cdr (sprio
));
118 Make sure they're in order of user input by adding index i.
119 Don't use the direction in this priority. Smaller means closer
124 Side_position_interface::set_axis (p
, Y_AXIS
);
125 p
->set_property ("script-priority", scm_int2num (prio
));
129 Script_engraver::process_music ()
131 for (int i
=0; i
< scripts_
.size (); i
++)
133 Music
* l
=scripts_
[i
].event_
;
135 Grob
* p
= make_item ("Script", l
->self_scm ());
137 make_script_from_event (p
, &scripts_
[i
].description_
, context (),
138 l
->get_property ("articulation-type"),
141 scripts_
[i
].script_
= p
;
144 SCM force_dir
= l
->get_property ("direction");
145 if (is_direction (force_dir
) && to_dir (force_dir
))
146 p
->set_property ("direction", force_dir
);
151 Script_engraver::acknowledge_grob (Grob_info inf
)
153 if (Stem::has_interface (inf
.grob_
))
155 for (int i
=0; i
< scripts_
.size (); i
++)
157 Grob
*e
= scripts_
[i
].script_
;
159 if (to_dir (e
->get_property ("side-relative-direction")))
160 e
->set_property ("direction-source", inf
.grob_
->self_scm ());
165 e
->add_dependency (inf
.grob_
);
166 Side_position_interface::add_support (e
, inf
.grob_
);
169 else if (Rhythmic_head::has_interface (inf
.grob_
))
171 for (int i
=0; i
< scripts_
.size (); i
++)
173 Grob
*e
= scripts_
[i
].script_
;
175 if (Side_position_interface::get_axis (e
) == X_AXIS
176 && !e
->get_parent (Y_AXIS
))
178 e
->set_parent (inf
.grob_
, Y_AXIS
);
179 e
->add_dependency (inf
.grob_
); // ??
181 Side_position_interface::add_support (e
,inf
.grob_
);
184 else if (Note_column::has_interface (inf
.grob_
))
188 We make note column the parent of the script. That's not
189 correct, but due to seconds in a chord, noteheads may be
190 swapped around horizontally. We don't know which note head to
191 put it on, so we postpone this decision to
192 Script_interface::before_line_breaking ().
195 for (int i
=0; i
< scripts_
.size (); i
++)
197 Grob
*e
= scripts_
[i
].script_
;
199 if (!e
->get_parent (X_AXIS
) &&
200 Side_position_interface::get_axis (e
) == Y_AXIS
)
202 e
->set_parent (inf
.grob_
, X_AXIS
);
209 Script_engraver::stop_translation_timestep ()
211 for (int i
=0; i
< scripts_
.size (); i
++)
213 if (!scripts_
[i
].script_
)
216 Grob
* sc
= scripts_
[i
].script_
;
218 SCM follow
= scm_assoc (ly_symbol2scm ("follow-into-staff"), scripts_
[i
].description_
);
219 if (ly_c_pair_p (follow
) && to_boolean (ly_cdr (follow
)))
221 sc
->add_offset_callback (Side_position_interface::quantised_position_proc
, Y_AXIS
);
222 sc
->set_property ("staff-padding", SCM_EOL
);
230 Script_engraver::Script_engraver (){}
232 ENTER_DESCRIPTION (Script_engraver
,
233 /* descr */ "Handles note scripted articulations.",
234 /* creats*/ "Script",
235 /* accepts */ "script-event articulation-event",
236 /* acks */ "stem-interface rhythmic-head-interface note-column-interface",
237 /* reads */ "scriptDefinitions",