2 notehead.cc -- implement Note_head
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
12 #include "note-head.hh"
14 #include "font-interface.hh"
15 #include "molecule.hh"
16 #include "musical-request.hh"
17 #include "rhythmic-head.hh"
20 Note_head contains the code for printing note heads.
26 It also contains the ledger lines, for historical reasons. Ledger
27 lines are somewhat of a PITA. In some cases, they take up no space, in
28 some cases they don't:
32 - when ledgered notes are juxtaposed: there should be some white
33 space between the ledger lines.
35 - when accidentals are near: the accidentals should not be on the ledger lines
37 [both tips by Heinz Stolba from Universal Edition].
39 DO NOT take space into account:
41 - for basically everything else, e.g. swapping ledgered notes on
42 clustered chords, spacing between ledgered and unledgered notes.
45 TODO: fix this. It is not feasible to have a special grob for
46 ledgers, since you basically don't know if there will be ledgers,
47 unless you know at interpretation phase already 1. the Y-position,
48 2. the number of staff lines. It's not yet specced when both pieces
49 of information are there, so for now, it is probably better to build
50 special support for ledgers into the accidental and separation-item
53 (Besides a separate ledger seems overkill. For what else would
60 #include "staff-symbol-referencer.hh"
63 build a ledger line for small pieces.
66 Note_head::ledger_line (Interval xwid, Grob *me)
68 Drul_array<Molecule> endings;
69 endings[LEFT] = Font_interface::get_default_font (me)->find_by_name ("noteheads-ledgerending");
70 Molecule *e = &endings[LEFT];
73 Real thick = e->extent (Y_AXIS).length ();
74 Real len = e->extent (X_AXIS).length () - thick;
79 endings[d].translate_axis (xwid[d] - endings[d].extent (X_AXIS)[d], X_AXIS);
80 total.add_molecule (endings[d]);
81 } while ((flip (&d)) != LEFT);
83 Real xpos = xwid [LEFT] + len;
85 while (xpos + len + thick /2 <= xwid[RIGHT])
87 e->translate_axis (len, X_AXIS);
88 total.add_molecule (*e);
97 Note_head::ledger_lines (Grob*me,
99 int count, Direction dir, Interval idw)
101 Real inter_f = Staff_symbol_referencer::staff_space (me)/2;
111 Molecule ledger (ledger_line (idw, me));
114 ledger.set_empty (true);
116 Real offs = (Staff_symbol_referencer::on_staffline (me))
121 for (int i=0; i < count; i++)
124 s.translate_axis (-dir * inter_f * i*2 + offs,
126 legs.add_molecule (s);
133 internal_brew_molecule (Grob *me, bool ledger_take_space)
135 int sz = Staff_symbol_referencer::line_count (me)-1;
136 int p = (int) rint (Staff_symbol_referencer::position_f (me));
137 int streepjes_i = abs (p) < sz
141 SCM style = me->get_grob_property ("style");
142 if (!gh_symbol_p (style))
148 ugh: use gh_call () / scm_apply ().
150 UGH: use grob-property.
152 SCM log = gh_int2scm (Rhythmic_head::balltype_i (me));
153 SCM exp = scm_list_n (ly_symbol2scm ("find-notehead-symbol"), log,
154 ly_quote_scm (style),
156 String name = "noteheads-" + ly_scm2string (scm_primitive_eval (exp));
157 Molecule out = Font_interface::get_default_font (me)->find_by_name (name);
161 Direction dir = (Direction)sign (p);
162 Interval hd = out.extent (X_AXIS);
163 Real hw = hd.length ()/4;
164 out.add_molecule (Note_head::ledger_lines (me, ledger_take_space, streepjes_i, dir,
165 Interval (hd[LEFT] - hw,
172 MAKE_SCHEME_CALLBACK (Note_head,brew_molecule,1);
174 Note_head::brew_molecule (SCM smob)
176 Grob *me = unsmob_grob (smob);
179 ledgers don't take space. See top of file.
181 return internal_brew_molecule (me, false).smobbed_copy ();
185 Compute the width the head without ledgers.
188 Note_head::head_extent (Grob *me, Axis a)
190 return internal_brew_molecule (me, false).extent (a);
194 Note_head::has_interface (Grob*m)
196 return m&& m->has_interface (ly_symbol2scm ("note-head-interface"));
200 MAKE_SCHEME_CALLBACK (Note_head,brew_ez_molecule,1);
203 TODO: ledger lines are causing a mess again, now with accidentals and
207 Note_head::brew_ez_molecule (SCM smob)
209 Grob *me = unsmob_grob (smob);
210 int l = Rhythmic_head::balltype_i (me);
213 SCM at = scm_list_n (ly_symbol2scm ("ez-ball"),
214 me->get_grob_property ("note-character"),
218 Box bx (Interval (0, 1.0), Interval (-0.5, 0.5));
220 int p = (int) rint (Staff_symbol_referencer::position_f (me));
222 int sz = Staff_symbol_referencer::line_count (me)-1;
223 int streepjes_i = abs (p) < sz
229 Direction dir = (Direction)sign (p);
230 Interval hd = m.extent (X_AXIS);
231 Real hw = hd.length ()/4;
232 m.add_molecule (ledger_lines (me, false, streepjes_i, dir,
233 Interval (hd[LEFT] - hw,
237 return m.smobbed_copy ();
242 Note_head::stem_attachment_coordinate (Grob *me, Axis a)
244 SCM v = me->get_grob_property ("stem-attachment-function");
246 if (!gh_procedure_p (v))
249 SCM st = me->get_grob_property ("style");
250 SCM result = gh_apply (v, scm_list_n (st, SCM_UNDEFINED));
252 if (!gh_pair_p (result))
255 result = (a == X_AXIS) ? ly_car (result) : ly_cdr (result);
257 return gh_number_p (result) ? gh_scm2double (result) : 0.0;