]> git.donarmstrong.com Git - lilypond.git/blob - lily/score-engraver.cc
* scm/layout-page-layout.scm (write-page-breaks): record tweaks
[lilypond.git] / lily / score-engraver.cc
1 /*
2   score-engraver.cc -- implement Score_engraver
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 "all-font-metrics.hh"
10 #include "warn.hh"
11 #include "main.hh"
12 #include "system.hh"
13 #include "score-engraver.hh"
14 #include "paper-score.hh"
15 #include "paper-column.hh"
16 #include "output-def.hh"
17 #include "axis-group-interface.hh"
18 #include "context-def.hh"
19 #include "global-context.hh"
20 #include "open-type-font.hh"
21 #include "paper-column-engraver.hh"
22
23 Score_engraver::Score_engraver ()
24 {
25   system_ = 0;
26   pscore_ = 0;
27 }
28
29 void
30 Score_engraver::derived_mark () const
31 {
32   if (pscore_)
33     scm_gc_mark (pscore_->self_scm ());
34   Score_translator::derived_mark ();
35   Engraver_group::derived_mark ();
36 }
37
38 void
39 Score_engraver::prepare (Moment m)
40 {
41   (void) m;
42
43   precomputed_recurse_over_translators (context (), START_TRANSLATION_TIMESTEP, DOWN);
44 }
45
46 void
47 Score_engraver::finish ()
48 {
49   recurse_over_translators (context (), &Translator::finalize,
50                             &Translator_group::finalize,
51                             UP);
52 }
53
54 #define MUSIC_FONT "emmentaler-20"
55
56 /*
57   use start/finish?
58 */
59 void
60 Score_engraver::initialize ()
61 {
62   Font_metric *fm = all_fonts_global->find_otf (MUSIC_FONT);
63   if (!fm)
64     {
65       error (_f ("cannot find `%s'", MUSIC_FONT ".otf")
66              + "\n"
67              + _ ("Music font has not been installed properly.")
68              + "\n"
69              + _f ("Search path `%s'", global_path.to_string ().c_str ())
70              + "\n"
71              + _ ("Aborting"));
72     }
73
74   pscore_ = new Paper_score (dynamic_cast<Output_def *> (context ()->get_output_def ()));
75   pscore_->unprotect ();
76
77   SCM props = updated_grob_properties (context (), ly_symbol2scm ("System"));
78
79   Object_key const *sys_key = context ()->get_grob_key ("System");
80   pscore_->typeset_system (new System (props, sys_key));
81   
82   system_ = pscore_->root_system ();
83   context ()->set_property ("rootSystem", system_->self_scm ());
84
85   Engraver_group::initialize ();
86 }
87
88 void
89 Score_engraver::finalize ()
90 {
91   Score_translator::finalize ();
92
93   typeset_all ();
94 }
95
96 void
97 Score_engraver::one_time_step ()
98 {
99   if (!to_boolean (context ()->get_property ("skipTypesetting")))
100     {
101       precomputed_recurse_over_translators (context (), PROCESS_MUSIC, UP);
102       Engraver_group::do_announces ();
103     }
104
105   precomputed_recurse_over_translators (context (), STOP_TRANSLATION_TIMESTEP, UP);
106   typeset_all ();
107 }
108
109 void
110 Score_engraver::announce_grob (Grob_info info)
111 {
112   announce_infos_.push (info);
113   pscore_->root_system ()->typeset_grob (info.grob ());
114   elems_.push (info.grob ());
115 }
116
117 void
118 Score_engraver::typeset_all ()
119 {
120   for (int i = 0; i < elems_.size (); i++)
121     {
122       Grob *elem = elems_[i];
123
124       if (!elem->get_parent (Y_AXIS))
125         Axis_group_interface::add_element (system_, elem);
126     }
127   elems_.clear ();
128 }
129
130 SCM
131 Score_engraver::get_output ()
132 {
133   Music_output *o = pscore_;
134   return o->self_scm ();
135 }
136
137 /*
138   UGH UGH
139 */
140 void
141 Score_engraver::forbid_breaks ()
142 {
143   for (SCM s = simple_trans_list_; scm_is_pair (s); s = scm_cdr (s))
144     {
145       Translator *tr = unsmob_translator (scm_car (s));
146       if (Paper_column_engraver *pce = dynamic_cast<Paper_column_engraver *> (tr))
147         pce->forbid_breaks ();
148     }
149 }
150
151 bool
152 Score_engraver::try_music (Music *m)
153 {
154   if (Engraver_group::try_music (m))
155     return true;
156
157   return false;
158 }
159
160 ADD_TRANSLATOR_GROUP (Score_engraver,
161                       /* doc */ "Top level engraver. Takes care of generating columns and the complete  system (ie. System) "
162                       "\n\n "
163                       "This engraver decides whether a column is breakable. The default is "
164                       "that a column is always breakable. However, when every Bar_engraver "
165                       "that does not have a barline at a certain point will call "
166                       "Score_engraver::forbid_breaks to stop linebreaks.  In practice, this "
167                       "means that you can make a breakpoint by creating a barline (assuming "
168                       "that there are no beams or notes that prevent a breakpoint.) ",
169                       /* create */
170                       "System ",
171
172                       /* accept */
173                       "break-event",
174                       /* read */
175                       "currentMusicalColumn "
176                       "currentCommandColumn "
177                       "verticallySpacedContexts",
178                       /* write */
179                       "");