2 multi_measure_rest-engraver.cc -- implement Multi_measure_rest_engraver
4 (c) 1998--2003 Jan Nieuwenhuizen <janneke@gnu.org>
5 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 #include "multi-measure-rest.hh"
10 #include "paper-column.hh"
11 #include "engraver-group-engraver.hh"
12 #include "side-position-interface.hh"
13 #include "staff-symbol-referencer.hh"
14 #include "engraver.hh"
19 The name says it all: make multi measure rests
22 class Multi_measure_rest_engraver
: public Engraver
25 TRANSLATOR_DECLARATIONS(Multi_measure_rest_engraver
);
28 virtual bool try_music (Music
*);
29 virtual void process_music ();
30 virtual void stop_translation_timestep ();
31 virtual void start_translation_timestep ();
32 virtual void finalize ();
36 Music
* busy_span_req_
;
38 Link_array
<Music
> text_events_
;
41 Rational last_main_moment_
;
44 Link_array
<Spanner
> numbers_
;
46 Link_array
<Spanner
> last_numbers_
;
50 Multi_measure_rest_engraver::Multi_measure_rest_engraver ()
55 new_req_
= busy_span_req_
= stop_req_
=0;
59 Multi_measure_rest_engraver::try_music (Music
* req
)
61 if (req
->is_mus_type ("multi-measure-rest-event"))
63 Direction d
= to_dir (req
->get_mus_property ("span-direction"));
68 else if (d
== START
&& !new_req_
)
74 else if (req
->is_mus_type ("multi-measure-text-event"))
76 text_events_
.push (req
);
83 Multi_measure_rest_engraver::process_music ()
85 if (new_req_
&& stop_req_
)
89 start_moment_
= now_mom ();
99 busy_span_req_
= new_req_
;
103 if (busy_span_req_
&& !mmrest_
)
105 mmrest_
= new Spanner (get_property ("MultiMeasureRest"));
107 if (text_events_
.size())
109 for (int i
= 0; i
< text_events_
.size(); i
++)
112 = new Spanner (get_property ("MultiMeasureRestText"));
114 Music
* e
= text_events_
[i
];
115 SCM t
= e
->get_mus_property ("text");
116 SCM dir
= e
->get_mus_property ("direction");
117 sp
->set_grob_property ("text",t
);
119 sp
->set_grob_property ("direction",dir
);
122 announce_grob (sp
, e
->self_scm());
126 Stack different scripts.
131 for (int i
=0; i
<numbers_
.size(); i
++)
133 if (gh_int2scm (d
) == numbers_
[i
]->get_grob_property ("direction"))
136 Side_position_interface::add_support (numbers_
[i
], last
);
140 } while (flip (&d
) != DOWN
);
145 = new Spanner (get_property ("MultiMeasureRestNumber"));
147 announce_grob (sp
, busy_span_req_
->self_scm());
150 for (int i
=0 ; i
< numbers_
.size(); i
++)
152 Side_position_interface::add_support (numbers_
[i
], mmrest_
);
153 numbers_
[i
]->set_parent (mmrest_
, Y_AXIS
);
156 announce_grob (mmrest_
, busy_span_req_
->self_scm());
158 = gh_scm2int (get_property ("currentBarNumber"));
161 if (gh_string_p (get_property ("whichBar")))
163 Grob
*cmc
= unsmob_grob (get_property( "currentCommandColumn"));
164 Item
*it
= dynamic_cast<Item
*> (cmc
);
167 add_bound_item (mmrest_
, it
);
168 for (int i
= 0; i
< numbers_
.size(); i
++)
169 add_bound_item (numbers_
[i
], it
);
174 add_bound_item (last_rest_
,it
);
175 for (int i
= 0; i
< last_numbers_
.size(); i
++)
176 add_bound_item (last_numbers_
[i
], it
);
182 Multi_measure_rest_engraver::stop_translation_timestep ()
184 SCM smp
= get_property ("measurePosition");
185 Moment mp
= (unsmob_moment (smp
)) ? *unsmob_moment (smp
) : Moment (0);
187 if (mmrest_
&& (now_mom () >= start_moment_
)
189 && mmrest_
->get_bound (LEFT
) && mmrest_
->get_bound (RIGHT
))
191 typeset_grob (mmrest_
);
192 for (int i
= 0 ; i
< numbers_
.size(); i
++)
194 typeset_grob (numbers_
[i
]);
195 Side_position_interface::add_staff_support (numbers_
[i
]);
199 we must keep mmrest_ around to set measure-count, so
207 if (last_rest_
->get_bound (LEFT
) && last_rest_
->get_bound (RIGHT
)
208 && last_rest_
->get_bound (LEFT
) != last_rest_
->get_bound (RIGHT
))
210 typeset_grob (last_rest_
);
212 for (int i
= 0; i
< last_numbers_
.size ();i
++)
214 typeset_grob (last_numbers_
[i
]);
215 Side_position_interface::add_staff_support (last_numbers_
[i
]);
219 last_numbers_
.clear();
224 busy_span_req_
= new_req_
;
228 text_events_
.clear ();
232 Multi_measure_rest_engraver::start_translation_timestep ()
234 SCM smp
= get_property ("measurePosition");
235 Moment mp
= (unsmob_moment (smp
)) ? *unsmob_moment (smp
) : Moment (0);
237 Moment now
=now_mom ();
239 && now
.main_part_
!= last_main_moment_
240 && mp
.main_part_
== Rational (0))
242 last_rest_
= mmrest_
;
243 last_numbers_
= numbers_
;
245 int cur
= gh_scm2int (get_property ("currentBarNumber"));
246 int num
= cur
- start_measure_
;
247 last_rest_
->set_grob_property ("measure-count", gh_int2scm (num
));
249 SCM sml
= get_property ("measureLength");
250 Rational ml
= (unsmob_moment (sml
)) ? unsmob_moment (sml
)->main_part_
: Rational (1);
251 if (ml
>= Rational (2))
253 last_rest_
->set_grob_property ("use-breve-rest", SCM_BOOL_T
);
259 Grob
* last
= last_numbers_
.size() ? last_numbers_
[0] : 0;
260 if (last
&& last
->get_grob_property ("text") == SCM_EOL
)
262 SCM thres
= get_property ("restNumberThreshold");
264 if (gh_number_p (thres
))
265 t
= gh_scm2int (thres
);
272 = scm_number_to_string (gh_int2scm (num
), SCM_MAKINUM (10));
273 last
->set_grob_property ("text", text
);
278 last_main_moment_
= now
.main_part_
;
282 Multi_measure_rest_engraver::finalize ()
286 typeset_grob (mmrest_
);
290 typeset_grob (last_rest_
);
293 for (int i
= 0; i
< last_numbers_
.size ();i
++)
294 typeset_grob (last_numbers_
[i
]);
296 for (int i
= 0; i
< numbers_
.size ();i
++)
297 typeset_grob (numbers_
[i
]);
301 ENTER_DESCRIPTION(Multi_measure_rest_engraver
,
303 "Engraves multi-measure rests that are produced with @code{R}. Reads "
304 "measurePosition and currentBarNumber to determine what number to print "
305 "over the MultiMeasureRest. Reads measureLength to determine if it "
306 "should use a whole rest or a breve rest to represent 1 measure "
308 /* creats*/ "MultiMeasureRest MultiMeasureRestNumber MultiMeasureRestText",
309 /* accepts */ "multi-measure-rest-event multi-measure-text-event",
311 /* reads */ "currentBarNumber restNumberThreshold currentCommandColumn measurePosition measureLength",