1 /*
2 This file is part of LilyPond, the GNU music typesetter.
3
4 Copyright (C) 2004--2021 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 "pointer-group-interface.hh"
21 #include "spanner.hh"
22 #include "engraver.hh"
23 #include "staff-symbol.hh"
24
25 #include "translator.icc"
26
27 using std::vector;
28
29 class Ledger_line_engraver : public Engraver
30 {
31 Spanner *span_;
32 vector<Grob *> ledgered_grobs_;
33
34 public:
35 TRANSLATOR_DECLARATIONS (Ledger_line_engraver);
36
37 protected:
38 void finalize () override;
39 void process_music ();
40
41 void acknowledge_ledgered (Grob_info);
42 void acknowledge_staff_symbol (Grob_info_t<Spanner>);
43
44 void start_spanner ();
45 void stop_spanner ();
46 void stop_translation_timestep ();
47 };
48
Ledger_line_engraver(Context * c)49 Ledger_line_engraver::Ledger_line_engraver (Context *c)
50 : Engraver (c)
51 {
52 span_ = 0;
53 }
54
55 void
start_spanner()56 Ledger_line_engraver::start_spanner ()
57 {
58 assert (!span_);
59
60 span_ = make_spanner ("LedgerLineSpanner", SCM_EOL);
61 auto *col = unsmob<Grob> (get_property (this, "currentCommandColumn"));
62 span_->set_bound (LEFT, col);
63 }
64
65 void
stop_translation_timestep()66 Ledger_line_engraver::stop_translation_timestep ()
67 {
68 if (span_)
69 {
70 for (vsize i = 0; i < ledgered_grobs_.size (); i++)
71 {
72 if (!from_scm<bool> (get_property (ledgered_grobs_[i], "no-ledgers")))
73 Pointer_group_interface::add_grob (span_,
74 ly_symbol2scm ("note-heads"),
75 ledgered_grobs_[i]);
76 }
77 }
78
79 ledgered_grobs_.clear ();
80 }
81
82 void
process_music()83 Ledger_line_engraver::process_music ()
84 {
85 /*
86 Need to do this, otherwise the first note might miss ledgers.
87 */
88 if (!span_)
89 start_spanner ();
90 }
91
92 void
finalize()93 Ledger_line_engraver::finalize ()
94 {
95 stop_spanner ();
96 }
97
98 void
stop_spanner()99 Ledger_line_engraver::stop_spanner ()
100 {
101 if (span_)
102 {
103 auto *col = unsmob<Grob> (get_property (this, "currentCommandColumn"));
104 span_->set_bound (RIGHT, col);
105 span_ = 0;
106 }
107 }
108
109 void
acknowledge_staff_symbol(Grob_info_t<Spanner> s)110 Ledger_line_engraver::acknowledge_staff_symbol (Grob_info_t<Spanner> s)
111 {
112 if (!span_ || (span_->get_bound (LEFT) != s.grob ()->get_bound (LEFT)))
113 {
114 stop_spanner ();
115 start_spanner ();
116 }
117 }
118
119 void
acknowledge_ledgered(Grob_info s)120 Ledger_line_engraver::acknowledge_ledgered (Grob_info s)
121 {
122 ledgered_grobs_.push_back (s.grob ());
123 }
124
125 void
boot()126 Ledger_line_engraver::boot ()
127 {
128 ADD_ACKNOWLEDGER (Ledger_line_engraver, ledgered);
129 ADD_ACKNOWLEDGER (Ledger_line_engraver, staff_symbol);
130 }
131
132 ADD_TRANSLATOR (Ledger_line_engraver,
133 /* doc */
134 "Create the spanner to draw ledger lines, and notices"
135 " objects that need ledger lines.",
136
137 /* create */
138 "LedgerLineSpanner ",
139
140 /* read */
141 "",
142
143 /* write */
144 ""
145 );
146