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