2 engraver-group-engraver.cc -- implement Engraver_group_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 #include "engraver-group-engraver.hh"
12 #include "paper-score.hh"
15 #include "translator-dispatch-list.hh"
18 Engraver_group_engraver::announce_grob (Grob_info info)
20 announce_infos_.push (info);
22 Engraver_group_engraver * dad_eng =
23 context_->get_parent_context ()
24 ? dynamic_cast<Engraver_group_engraver*> (context_->get_parent_context ()->implementation ())
27 dad_eng->announce_grob (info);
30 SCM find_acknowledge_engravers (SCM gravlist, SCM meta);
31 SCM find_accept_engravers (SCM gravlist, SCM music_descr);
34 Engraver_group_engraver::acknowledge_grobs ()
36 if (!announce_infos_.size ())
39 SCM name_sym = ly_symbol2scm ("name");
40 SCM meta_sym = ly_symbol2scm ("meta");
42 for (int j = 0; j < announce_infos_.size (); j++)
44 Grob_info info = announce_infos_[j];
46 SCM meta = info.grob ()->internal_get_property (meta_sym);
47 SCM nm = scm_assoc (name_sym, meta);
53 it's tempting to put an assert for
54 immutable_property_alist_ == '(), but in fact, some
55 engravers (clef-engraver) add some more information to the
56 immutable_property_alist_ (after it has been '()-ed).
58 We ignore the grob anyway. He who has no name, shall not
64 SCM acklist = scm_hashq_ref (acknowledge_hash_table_, nm, SCM_UNDEFINED);
65 Engraver_dispatch_list *dispatch
66 = Engraver_dispatch_list::unsmob (acklist);
68 if (acklist == SCM_BOOL_F)
71 = scm_cdr (scm_assoc (ly_symbol2scm ("interfaces"), meta));
72 acklist = Engraver_dispatch_list::create (get_simple_trans_list (),
76 = Engraver_dispatch_list::unsmob (acklist);
79 scm_hashq_set_x (acknowledge_hash_table_, nm, acklist);
85 dispatch->apply (info);
89 if (acklist == SCM_BOOL_F)
91 acklist = find_acknowledge_engravers (get_simple_trans_list (),
93 scm_hashq_set_x (acknowledge_hash_table_, nm, acklist);
96 for (SCM p = acklist; scm_is_pair (p); p = scm_cdr (p))
98 Translator *t = unsmob_translator (scm_car (p));
99 Engraver *eng = dynamic_cast<Engraver *> (t);
100 if (eng && eng != info.origin_translator ())
101 eng->acknowledge_grob (info);
107 Ugh. This is slightly expensive. We could/should cache the value of
111 Engraver_group_engraver::pending_grob_count () const
113 int count = announce_infos_.size ();
114 for (SCM s = context_->children_contexts ();
115 scm_is_pair (s); s = scm_cdr (s))
117 Context *c = unsmob_context (scm_car (s));
118 Engraver_group_engraver *group
119 = dynamic_cast<Engraver_group_engraver *> (c->implementation ());
122 count += group->pending_grob_count ();
128 Engraver_group_engraver::do_announces ()
132 for (SCM s = context ()->children_contexts ();
133 scm_is_pair (s); s = scm_cdr (s))
135 Context *c = unsmob_context (scm_car (s));
136 Engraver_group_engraver *group
137 = dynamic_cast<Engraver_group_engraver *> (c->implementation ());
139 group->do_announces ();
144 precomputed_translator_foreach (PROCESS_ACKNOWLEDGED);
145 if (announce_infos_.size () == 0)
148 acknowledge_grobs ();
149 announce_infos_.clear ();
152 while (pending_grob_count () > 0);
156 Engraver_group_engraver::Engraver_group_engraver ()
158 acknowledge_hash_table_ = SCM_EOL;
159 acknowledge_hash_table_ = scm_c_make_hash_table (61);
162 #include "translator.icc"
164 ADD_TRANSLATOR_GROUP (Engraver_group_engraver,
165 /* descr */ "A group of engravers taken together",
174 engraver_valid (Translator *tr, SCM ifaces)
176 SCM ack_ifs = scm_assoc (ly_symbol2scm ("interfaces-acked"),
177 tr->translator_description ());
178 ack_ifs = scm_cdr (ack_ifs);
179 for (SCM s = ifaces; scm_is_pair (s); s = scm_cdr (s))
180 if (scm_c_memq (scm_car (s), ack_ifs) != SCM_BOOL_F)
186 find_acknowledge_engravers (SCM gravlist, SCM ifaces)
189 for (SCM s = gravlist; scm_is_pair (s); s = scm_cdr (s))
191 Translator *tr = unsmob_translator (scm_car (s));
192 if (engraver_valid (tr, ifaces))
193 l = scm_cons (tr->self_scm (), l);
195 l = scm_reverse_x (l, SCM_EOL);
201 Engraver_group_engraver::derived_mark () const
203 scm_gc_mark (acknowledge_hash_table_);