]> git.donarmstrong.com Git - lilypond.git/blob - lily/measure-grouping-engraver.cc
Issue 5167/3: Split off `markup-lambda' from `define-markup-command'
[lilypond.git] / lily / measure-grouping-engraver.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2002--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "warn.hh"
21 #include "side-position-interface.hh"
22 #include "global-context.hh"
23 #include "engraver.hh"
24 #include "spanner.hh"
25
26 #include "translator.icc"
27
28 class Measure_grouping_engraver : public Engraver
29 {
30 public:
31   TRANSLATOR_DECLARATIONS (Measure_grouping_engraver);
32
33 protected:
34   Spanner *grouping_;
35   Rational stop_grouping_mom_;
36
37   void process_music ();
38   virtual void finalize ();
39   void acknowledge_note_column (Grob_info);
40 };
41
42 void
43 Measure_grouping_engraver::finalize ()
44 {
45   if (grouping_)
46     {
47       grouping_->set_bound (RIGHT, unsmob<Grob> (get_property ("currentCommandColumn")));
48       grouping_->suicide ();
49       grouping_ = 0;
50     }
51 }
52
53 void
54 Measure_grouping_engraver::acknowledge_note_column (Grob_info gi)
55 {
56   if (grouping_)
57     Side_position_interface::add_support (grouping_, gi.grob ());
58 }
59
60 void
61 Measure_grouping_engraver::process_music ()
62 {
63   Moment now = now_mom ();
64   if (grouping_ && now.main_part_ >= stop_grouping_mom_ && !now.grace_part_)
65     {
66       grouping_->set_bound (RIGHT,
67                             unsmob<Grob> (get_property ("currentMusicalColumn")));
68
69       grouping_ = 0;
70     }
71
72   if (now.grace_part_)
73     return;
74
75   SCM grouping = get_property ("beatStructure");
76   if (scm_is_pair (grouping))
77     {
78       Moment *measpos = unsmob<Moment> (get_property ("measurePosition"));
79       Rational mp = measpos->main_part_;
80
81       Moment *base_mom = unsmob<Moment> (get_property ("baseMoment"));
82       Rational base_moment = base_mom->main_part_;
83
84       Rational where (0);
85       for (SCM s = grouping; scm_is_pair (s);
86            where += Rational ((int) scm_to_int (scm_car (s))) * base_moment,
87            s = scm_cdr (s))
88         {
89           int grouplen = scm_to_int (scm_car (s));
90           if (where == mp)
91             {
92               if (grouping_)
93                 {
94                   programming_error ("last grouping not finished yet");
95                   continue;
96                 }
97               if (grouplen > 1)
98                 {
99                   grouping_ = make_spanner ("MeasureGrouping", SCM_EOL);
100                   grouping_->set_bound (LEFT, unsmob<Grob> (get_property ("currentMusicalColumn")));
101
102                   stop_grouping_mom_ = now.main_part_ + Rational (grouplen - 1) * base_moment;
103                   get_global_context ()->add_moment_to_process (Moment (stop_grouping_mom_));
104
105                   if (grouplen == 3)
106                     grouping_->set_property ("style", ly_symbol2scm ("triangle"));
107                   else
108                     grouping_->set_property ("style", ly_symbol2scm ("bracket"));
109
110                   break;
111                 }
112             }
113         }
114     }
115 }
116
117 Measure_grouping_engraver::Measure_grouping_engraver (Context *c)
118   : Engraver (c)
119 {
120   grouping_ = 0;
121 }
122
123 void
124 Measure_grouping_engraver::boot ()
125 {
126   ADD_ACKNOWLEDGER (Measure_grouping_engraver, note_column);
127 }
128
129 ADD_TRANSLATOR (Measure_grouping_engraver,
130                 /* doc */
131                 "Create @code{MeasureGrouping} to indicate beat subdivision.",
132
133                 /* create */
134                 "MeasureGrouping ",
135
136                 /* read */
137                 "baseMoment "
138                 "beatStructure "
139                 "currentMusicalColumn "
140                 "measurePosition ",
141
142                 /* write */
143                 ""
144                );