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