lilypond-1.3.124
[lilypond.git] / lily / custos.cc
blobef3399d7ec6199bfc3bdb048d28bc3326684a77c
1 /*
2 custos.cc -- implement Custos
4 source file of the GNU LilyPond music typesetter
6 (C) 2000 Juergen Reuter <reuterj@ira.uka.de>
7 */
9 /* TODO:
11 - merge create_ledger_line () and Note_head::create_ledger_line()
14 - rewrite create_ledger_line() to support short and thin ledger lines
16 - do not show if a clef change immediately follows in the next line
18 - make custos direction control configurable
20 - decide: do or do not print custos if the next line starts with a rest
25 #include <stdio.h>
26 #include "staff-symbol-referencer.hh"
27 #include "custos.hh"
28 #include "molecule.hh"
29 #include "lookup.hh"
30 #include "debug.hh"
31 #include "note-head.hh"
32 #include "item.hh"
33 #include "font-interface.hh"
36 This function is a patched and hopefully much more understandable
37 rewrite of Note_head::ledger_line(). It still has some
38 bugs/limitations:
40 (1) The term thick/2 probably should be thick*2 (probably a bug,
41 see the code below).
43 (2) The minimal width of the resulting ledger line equals the width
44 of the noteheads-ledgerending symbol (a limitation):
46 (---- left ledger ending
47 ----) right ledger ending
48 (---) resulting ledger line (just ok)
50 If x_extent ("xwid" in Note_head) is less than the width of the
51 ledger ending, the width of the total ledger line is even *greater*
52 than the width of a ledger ending (I would call this a bug). In
53 the below code, the condition "if (x_extent.length() >
54 slice_x_extent.length())" avoids outputting the left ending in such
55 cases (rather a silly workaround, but better than nothing).
57 (---- left ledger ending
58 ----) right ledger ending
59 (-) desired ledger line
60 ------- resulting ledger line (too long)
61 ----) resulting ledger line with additional "if" (still too long)
63 The algorithm works properly only for a desired ledger line width
64 greater than the width of the ledger ending:
66 (---- left ledger ending
67 ----) right ledger ending
68 (------) desired ledger line
69 (------) resulting ledger line (ok)
71 * (3) The thickness of the ledger line is fixed (limitation).
73 Molecule
74 Custos::create_ledger_line (Interval x_extent, Grob *me)
76 Molecule line;
77 Molecule slice = Font_interface::get_default_font (me)->find_by_name ("noteheads-ledgerending");
78 Interval slice_x_extent = slice.extent(X_AXIS);
79 Interval slice_y_extent = slice.extent(Y_AXIS);
81 // Create left ending of ledger line.
82 Molecule left_ending = slice;
83 left_ending.translate_axis (x_extent[LEFT] - slice_x_extent[LEFT], X_AXIS);
84 if (x_extent.length() > slice_x_extent.length())
85 line.add_molecule (left_ending);
87 // Create right ending of ledger line.
88 Molecule right_ending = slice;
89 right_ending.translate_axis (x_extent[RIGHT] - slice_x_extent[RIGHT],
90 X_AXIS);
91 line.add_molecule (right_ending);
93 // Fill out space between left and right ending of ledger line by
94 // lining up a series of slices in a row between them.
95 Molecule fill_out_slice = left_ending;
96 Real thick = slice_y_extent.length();
97 Real delta_x = slice_x_extent.length () - thick;
98 Real xpos = x_extent [LEFT] + 2*delta_x + thick/2; // TODO: check: thick*2?
99 while (xpos <= x_extent[RIGHT])
101 fill_out_slice.translate_axis (delta_x, X_AXIS);
102 line.add_molecule (fill_out_slice);
103 xpos += delta_x;
106 return line;
109 void
110 Custos::add_streepjes(Grob* me,
111 int pos,
112 int interspaces,
113 Molecule* custos_p_)
115 // TODO: This is (almost) duplicated code (see
116 // Note_head::brew_molecule). Junk me.
117 Real inter_f = Staff_symbol_referencer::staff_space (me)/2;
118 int streepjes_i = abs (pos) < interspaces
120 : (abs(pos) - interspaces) /2;
121 if (streepjes_i)
123 Direction dir = (Direction)sign (pos);
124 Molecule ledger_line (create_ledger_line (custos_p_->extent (X_AXIS),
125 me));
126 ledger_line.set_empty (true);
127 Real offs = (Staff_symbol_referencer::on_staffline (me))
128 ? 0.0
129 : -dir * inter_f;
130 for (int i = 0; i < streepjes_i; i++)
132 Molecule streep (ledger_line);
133 streep.translate_axis (-dir * inter_f * i * 2 + offs,
134 Y_AXIS);
135 custos_p_->add_molecule (streep);
140 MAKE_SCHEME_CALLBACK(Custos,brew_molecule,1);
142 Custos::brew_molecule (SCM smob)
144 Item *me = (Item *)unsmob_grob (smob);
145 SCM scm_style = me->get_grob_property ("style");
147 if (gh_symbol_p (scm_style))
149 String style = ly_scm2string (scm_symbol_to_string (scm_style));
151 String idx = "custodes-";
152 int interspaces = Staff_symbol_referencer::line_count (me)-1;
154 Real pos = Staff_symbol_referencer::position_f (me);
156 if (pos > (interspaces/2 + 1)) // TODO: make this rule configurable
157 idx += "r";
158 idx += style;
159 Molecule molecule
160 = Font_interface::get_default_font (me)->find_by_name (idx);
161 if (molecule.empty_b())
163 String message = "unknown custos style: `" + style + "'";
164 warning(_ (message.ch_C()));
165 return SCM_EOL;
167 else
169 add_streepjes(me, (int)pos, interspaces, &molecule);
170 return molecule.smobbed_copy();
173 else
174 return SCM_EOL;
177 bool
178 Custos::has_interface (Grob*m)
180 return m && m->has_interface (ly_symbol2scm ("custos-interface"));