]> git.donarmstrong.com Git - lilypond.git/blob - lily/engraver-group.cc
*** empty log message ***
[lilypond.git] / lily / engraver-group.cc
1 /*
2   engraver-group-engraver.cc -- implement Engraver_group
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "engraver-group-engraver.hh"
10
11 #include "warn.hh"
12 #include "paper-score.hh"
13 #include "grob.hh"
14 #include "context.hh"
15 #include "translator-dispatch-list.hh"
16
17 void
18 Engraver_group::announce_grob (Grob_info info)
19 {
20   announce_infos_.push (info);
21
22   Engraver_group *dad_eng
23     = context_->get_parent_context ()
24     ? dynamic_cast<Engraver_group *> (context_->get_parent_context ()->implementation ())
25     : 0;
26   if (dad_eng)
27     dad_eng->announce_grob (info);
28 }
29
30 void
31 Engraver_group::acknowledge_grobs ()
32 {
33   if (!announce_infos_.size ())
34     return;
35
36   SCM name_sym = ly_symbol2scm ("name");
37   SCM meta_sym = ly_symbol2scm ("meta");
38
39   for (int j = 0; j < announce_infos_.size (); j++)
40     {
41       Grob_info info = announce_infos_[j];
42
43       SCM meta = info.grob ()->internal_get_property (meta_sym);
44       SCM nm = scm_assoc (name_sym, meta);
45       if (scm_is_pair (nm))
46         nm = scm_cdr (nm);
47       else
48         continue;
49
50       SCM acklist = scm_hashq_ref (acknowledge_hash_table_, nm, SCM_BOOL_F);
51       Engraver_dispatch_list *dispatch
52         = Engraver_dispatch_list::unsmob (acklist);
53
54       if (acklist == SCM_BOOL_F)
55         {
56           SCM ifaces
57             = scm_cdr (scm_assoc (ly_symbol2scm ("interfaces"), meta));
58           acklist = Engraver_dispatch_list::create (get_simple_trans_list (),
59                                                     ifaces);
60
61           dispatch
62             = Engraver_dispatch_list::unsmob (acklist);
63
64           scm_hashq_set_x (acknowledge_hash_table_, nm, acklist);
65         }
66
67       if (dispatch)
68         dispatch->apply (info);
69     }
70 }
71
72 /*
73   Ugh. This is slightly expensive. We could/should cache the value of
74   the group count?
75 */
76 int
77 Engraver_group::pending_grob_count () const
78 {
79   int count = announce_infos_.size ();
80   for (SCM s = context_->children_contexts ();
81        scm_is_pair (s); s = scm_cdr (s))
82     {
83       Context *c = unsmob_context (scm_car (s));
84       Engraver_group *group
85         = dynamic_cast<Engraver_group *> (c->implementation ());
86
87       if (group)
88         count += group->pending_grob_count ();
89     }
90   return count;
91 }
92
93 void
94 Engraver_group::do_announces ()
95 {
96   do
97     {
98       for (SCM s = context ()->children_contexts ();
99            scm_is_pair (s); s = scm_cdr (s))
100         {
101           Context *c = unsmob_context (scm_car (s));
102           Engraver_group *group
103             = dynamic_cast<Engraver_group *> (c->implementation ());
104           if (group)
105             group->do_announces ();
106         }
107
108       while (1)
109         {
110           precomputed_translator_foreach (PROCESS_ACKNOWLEDGED);
111           if (announce_infos_.size () == 0)
112             break;
113
114           acknowledge_grobs ();
115           announce_infos_.clear ();
116         }
117     }
118   while (pending_grob_count () > 0);
119 }
120
121 Engraver_group::Engraver_group ()
122 {
123   acknowledge_hash_table_ = SCM_EOL;
124   acknowledge_hash_table_ = scm_c_make_hash_table (61);
125 }
126
127 #include "translator.icc"
128
129 ADD_TRANSLATOR_GROUP (Engraver_group,
130                       /* doc */ "A group of engravers taken together",
131                       /* create */ "",
132                       /* accept */ "",
133                       /* read */ "",
134                       /* write */ "");
135
136 void
137 Engraver_group::derived_mark () const
138 {
139   scm_gc_mark (acknowledge_hash_table_);
140 }