2 custos.cc -- implement Custos
4 source file of the GNU LilyPond music typesetter
6 (C) 2000, 2002 Juergen Reuter <reuter@ipd.uka.de>
11 - merge create_ledger_line () and Note_head::create_ledger_line ()
13 - rewrite create_ledger_line () to support short and thin ledger lines
15 - do not show if a clef change immediately follows in the next line
17 - decide: do or do not print custos if the next line starts with a rest
23 #include "direction.hh"
24 #include "staff-symbol-referencer.hh"
26 #include "molecule.hh"
28 #include "note-head.hh"
30 #include "font-interface.hh"
31 #include "math.h" // rint
34 This function is a patched and hopefully much more understandable
35 rewrite of Note_head::ledger_line (). It still has some
38 (1) The term thick/2 probably should be thick*2 (probably a bug,
41 (2) The minimal width of the resulting ledger line equals the width
42 of the noteheads-ledgerending symbol (a limitation):
44 (---- left ledger ending
45 ----) right ledger ending
46 (---) resulting ledger line (just ok)
48 If x_extent ("xwid" in Note_head) is less than the width of the
49 ledger ending, the width of the total ledger line is even *greater*
50 than the width of a ledger ending (I would call this a bug). In
51 the below code, the condition "if (x_extent.length () >
52 slice_x_extent.length ())" avoids outputting the left ending in such
53 cases (rather a silly workaround, but better than nothing).
55 (---- left ledger ending
56 ----) right ledger ending
57 (-) desired ledger line
58 ------- resulting ledger line (too long)
59 ----) resulting ledger line with additional "if" (still too long)
61 The algorithm works properly only for a desired ledger line width
62 greater than the width of the ledger ending:
64 (---- left ledger ending
65 ----) right ledger ending
66 (------) desired ledger line
67 (------) resulting ledger line (ok)
69 * (3) The thickness of the ledger line is fixed (limitation).
72 Custos::create_ledger_line (Interval x_extent, Grob *me)
75 Molecule slice = Font_interface::get_default_font (me)->find_by_name ("noteheads-ledgerending");
76 Interval slice_x_extent = slice.extent (X_AXIS);
77 Interval slice_y_extent = slice.extent (Y_AXIS);
79 // Create left ending of ledger line.
80 Molecule left_ending = slice;
81 left_ending.translate_axis (x_extent[LEFT] - slice_x_extent[LEFT], X_AXIS);
82 if (x_extent.length () > slice_x_extent.length ())
83 line.add_molecule (left_ending);
85 // Create right ending of ledger line.
86 Molecule right_ending = slice;
87 right_ending.translate_axis (x_extent[RIGHT] - slice_x_extent[RIGHT],
89 line.add_molecule (right_ending);
91 // Fill out space between left and right ending of ledger line by
92 // lining up a series of slices in a row between them.
93 Molecule fill_out_slice = left_ending;
94 Real thick = slice_y_extent.length ();
95 Real delta_x = slice_x_extent.length () - thick;
96 Real xpos = x_extent [LEFT] + 2*delta_x + thick/2; // TODO: check: thick*2?
97 while (xpos <= x_extent[RIGHT])
99 fill_out_slice.translate_axis (delta_x, X_AXIS);
100 line.add_molecule (fill_out_slice);
108 Custos::add_streepjes (Grob* me,
113 // TODO: This is (almost) duplicated code (see
114 // Note_head::brew_molecule). Junk me.
115 Real inter_f = Staff_symbol_referencer::staff_space (me)/2;
116 int streepjes_i = abs (pos) < interspaces
118 : (abs (pos) - interspaces) /2;
121 Direction dir = (Direction)sign (pos);
122 Molecule ledger_line (create_ledger_line (custos_p_->extent (X_AXIS),
124 ledger_line.set_empty (true);
125 Real offs = (Staff_symbol_referencer::on_staffline (me))
128 for (int i = 0; i < streepjes_i; i++)
130 Molecule streep (ledger_line);
131 streep.translate_axis (-dir * inter_f * i * 2 + offs,
133 custos_p_->add_molecule (streep);
138 MAKE_SCHEME_CALLBACK (Custos,brew_molecule,1);
140 Custos::brew_molecule (SCM smob)
142 Item *me = (Item *)unsmob_grob (smob);
143 SCM scm_style = me->get_grob_property ("style");
145 if (gh_symbol_p (scm_style))
147 String style = ly_scm2string (scm_symbol_to_string (scm_style));
152 Why would we want it differently? What's the meaning of adjust ?
155 to_boolean (me->get_grob_property ("adjust-if-on-staffline"));
157 String idx = "custodes-" + style + "-";
160 SCM ntr_pos = me->get_grob_property ("neutral-position");
161 if (gh_number_p (ntr_pos))
162 neutral_pos = gh_scm2int (ntr_pos);
166 Direction neutral_direction =
167 to_dir (me->get_grob_property ("neutral-direction"));
169 int pos = (int)rint (Staff_symbol_referencer::position_f (me));
170 int sz = Staff_symbol_referencer::line_count (me)-1;
172 if (pos < neutral_pos)
174 else if (pos > neutral_pos)
176 else if (neutral_direction == UP)
178 else if (neutral_direction == DOWN)
180 else // auto direction; not yet supported -> use "d"
185 idx += (((pos ^ sz) & 0x1) == 0) ? "1" : "0";
193 = Font_interface::get_default_font (me)->find_by_name (idx);
194 if (molecule.empty_b ())
196 String message = "no such custos: `" + idx + "'";
197 warning (_ (message.ch_C ()));
202 add_streepjes (me, (int)pos, sz, &molecule);
203 return molecule.smobbed_copy ();
211 Custos::has_interface (Grob*m)
213 return m && m->has_interface (ly_symbol2scm ("custos-interface"));
217 ADD_INTERFACE (Custos, "custos-interface",
218 "A custos is a staff context symbol that appears at the end of a
219 staff line with monophonic musical contents (i.e. with a single
220 voice). It anticipates the pitch of the first note of the following
221 line and thus helps the player or singer to manage line breaks
222 during performance, thus enhancing readability of a score.
224 Custodes were frequently used in music notation until the 16th
225 century. There were different appearences for different notation
226 styles. Nowadays, they have survived only in special forms of
227 musical notation such as via the editio vaticana dating back to the
228 beginning of the 20th century.
230 [TODO: add to glossary]",
231 "style adjust-if-on-staffline neutral-position");