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 (gh_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 (gh_pair_p (entry
))
75 g
->internal_set_property (sym
, gh_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 (gh_pair_p (sprio
))
114 prio
= gh_scm2int (gh_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", gh_int2scm (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");
137 make_script_from_event (p
, &scripts_
[i
].description_
, daddy_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
);
149 announce_grob (p
, l
->self_scm ());
154 Script_engraver::acknowledge_grob (Grob_info inf
)
156 if (Stem::has_interface (inf
.grob_
))
158 for (int i
=0; i
< scripts_
.size (); i
++)
160 Grob
*e
= scripts_
[i
].script_
;
162 if (to_dir (e
->get_property ("side-relative-direction")))
163 e
->set_property ("direction-source", inf
.grob_
->self_scm ());
168 e
->add_dependency (inf
.grob_
);
169 Side_position_interface::add_support (e
, inf
.grob_
);
172 else if (Rhythmic_head::has_interface (inf
.grob_
))
174 for (int i
=0; i
< scripts_
.size (); i
++)
176 Grob
*e
= scripts_
[i
].script_
;
178 if (Side_position_interface::get_axis (e
) == X_AXIS
179 && !e
->get_parent (Y_AXIS
))
181 e
->set_parent (inf
.grob_
, Y_AXIS
);
182 e
->add_dependency (inf
.grob_
); // ??
184 Side_position_interface::add_support (e
,inf
.grob_
);
187 else if (Note_column::has_interface (inf
.grob_
))
191 We make note column the parent of the script. That's not
192 correct, but due to seconds in a chord, noteheads may be
193 swapped around horizontally. We don't know which note head to
194 put it on, so we postpone this decision to
195 Script_interface::before_line_breaking ().
198 for (int i
=0; i
< scripts_
.size (); i
++)
200 Grob
*e
= scripts_
[i
].script_
;
202 if (!e
->get_parent (X_AXIS
) &&
203 Side_position_interface::get_axis (e
) == Y_AXIS
)
205 e
->set_parent (inf
.grob_
, X_AXIS
);
212 Script_engraver::stop_translation_timestep ()
214 for (int i
=0; i
< scripts_
.size (); i
++)
216 if (!scripts_
[i
].script_
)
219 Grob
* sc
= scripts_
[i
].script_
;
221 SCM follow
= scm_assoc (ly_symbol2scm ("follow-into-staff"), scripts_
[i
].description_
);
222 if (gh_pair_p (follow
) && to_boolean (gh_cdr (follow
)))
224 sc
->add_offset_callback (Side_position_interface::quantised_position_proc
, Y_AXIS
);
225 sc
->set_property ("staff-padding", SCM_EOL
);
234 Script_engraver::Script_engraver (){}
236 ENTER_DESCRIPTION (Script_engraver
,
237 /* descr */ "Handles note scripted articulations.",
238 /* creats*/ "Script",
239 /* accepts */ "script-event articulation-event",
240 /* acks */ "stem-interface rhythmic-head-interface note-column-interface",
241 /* reads */ "scriptDefinitions",