]> git.donarmstrong.com Git - lilypond.git/blob - lily/engraver-group.cc
Fix some bugs in the dynamic engraver and PostScript backend
[lilypond.git] / lily / engraver-group.cc
1 /*
2   engraver-group.cc -- implement Engraver_group
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "engraver-group.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_back (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
27   if (dad_eng)
28     dad_eng->announce_grob (info);
29 }
30
31 void
32 Engraver_group::acknowledge_grobs ()
33 {
34   if (!announce_infos_.size ())
35     return;
36
37   SCM name_sym = ly_symbol2scm ("name");
38   SCM meta_sym = ly_symbol2scm ("meta");
39
40   for (vsize j = 0; j < announce_infos_.size (); j++)
41     {
42       Grob_info info = announce_infos_[j];
43       
44       SCM meta = info.grob ()->internal_get_property (meta_sym);
45       SCM nm = scm_assoc (name_sym, meta);
46       if (scm_is_pair (nm))
47         nm = scm_cdr (nm);
48       else
49         continue;
50
51       SCM acklist = scm_hashq_ref (acknowledge_hash_table_drul_[info.start_end()],
52                                    nm, SCM_BOOL_F);
53       
54       Engraver_dispatch_list *dispatch
55         = Engraver_dispatch_list::unsmob (acklist);
56
57       if (acklist == SCM_BOOL_F)
58         {
59           SCM ifaces
60             = scm_cdr (scm_assoc (ly_symbol2scm ("interfaces"), meta));
61           acklist = Engraver_dispatch_list::create (get_simple_trans_list (),
62                                                     ifaces, info.start_end ());
63
64           dispatch
65             = Engraver_dispatch_list::unsmob (acklist);
66
67           scm_hashq_set_x (acknowledge_hash_table_drul_[info.start_end ()], nm, acklist);
68         }
69
70       if (dispatch)
71         dispatch->apply (info);
72     }
73 }
74
75 /*
76   Ugh. This is slightly expensive. We could/should cache the value of
77   the group count?
78 */
79 int
80 Engraver_group::pending_grob_count () const
81 {
82   int count = announce_infos_.size ();
83   for (SCM s = context_->children_contexts ();
84        scm_is_pair (s); s = scm_cdr (s))
85     {
86       Context *c = unsmob_context (scm_car (s));
87       Engraver_group *group
88         = dynamic_cast<Engraver_group *> (c->implementation ());
89
90       if (group)
91         count += group->pending_grob_count ();
92     }
93   return count;
94 }
95
96 void
97 Engraver_group::do_announces ()
98 {
99   do
100     {
101       /*
102         DOCME: why is this inside the loop? 
103        */
104       for (SCM s = context ()->children_contexts ();
105            scm_is_pair (s); s = scm_cdr (s))
106         {
107           Context *c = unsmob_context (scm_car (s));
108           Engraver_group *group
109             = dynamic_cast<Engraver_group *> (c->implementation ());
110           if (group)
111             group->do_announces ();
112         }
113
114       
115       while (1)
116         {
117           precomputed_translator_foreach (PROCESS_ACKNOWLEDGED);
118           if (announce_infos_.size () == 0)
119             break;
120
121           acknowledge_grobs ();
122           announce_infos_.clear ();
123         }
124     }
125   while (pending_grob_count () > 0);
126 }
127
128 Engraver_group::Engraver_group ()
129 {
130   acknowledge_hash_table_drul_[LEFT] 
131     = acknowledge_hash_table_drul_[RIGHT] 
132     = SCM_EOL;
133   
134   acknowledge_hash_table_drul_[LEFT] = scm_c_make_hash_table (61);
135   acknowledge_hash_table_drul_[RIGHT] = scm_c_make_hash_table (61);
136 }
137
138 #include "translator.icc"
139
140 ADD_TRANSLATOR_GROUP (Engraver_group,
141                       /* doc */ "A group of engravers taken together",
142                       /* create */ "",
143                       /* accept */ "",
144                       /* read */ "",
145                       /* write */ "");
146
147 void
148 Engraver_group::derived_mark () const
149 {
150   scm_gc_mark (acknowledge_hash_table_drul_[LEFT]);
151   scm_gc_mark (acknowledge_hash_table_drul_[RIGHT]);
152 }