2 paper-column.cc -- implement Paper_column
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
9 #include "paper-column.hh"
12 #include "paper-score.hh"
14 #include "axis-group-interface.hh"
15 #include "spaceable-grob.hh"
16 #include "text-interface.hh"
18 #include "font-interface.hh"
19 #include "output-def.hh"
20 #include "pointer-group-interface.hh"
21 #include "grob-array.hh"
25 #include "string-convert.hh"
28 Paper_column::clone (int count) const
30 return new Paper_column (*this, count);
34 Paper_column::do_break_processing ()
36 Item::do_break_processing ();
40 Paper_column::get_rank (Grob const *me)
42 return dynamic_cast<Paper_column const *> (me)->rank_;
46 Paper_column::get_system () const
52 Paper_column::set_system (System *s)
58 Paper_column::get_column () const
60 return (Paper_column *) (this);
63 Paper_column::Paper_column (SCM l, Object_key const *key)
64 : Item (l, key) // guh.?
70 Paper_column::Paper_column (Paper_column const &src, int count)
78 Paper_column::compare (Grob * const &a,
81 return sign (dynamic_cast<Paper_column*> (a)->rank_
82 - dynamic_cast<Paper_column*> (b)->rank_);
86 Paper_column::less_than (Grob *const &a,
89 Paper_column *pa = dynamic_cast<Paper_column*> (a);
90 Paper_column *pb = dynamic_cast<Paper_column*> (b);
92 return pa->rank_ < pb->rank_;
96 Paper_column::when_mom (Grob *me)
98 SCM m = me->get_property ("when");
99 if (Moment *when = unsmob_moment (m))
105 Paper_column::is_musical (Grob *me)
107 SCM m = me->get_property ("shortest-starter-duration");
109 if (unsmob_moment (m))
110 s = *unsmob_moment (m);
111 return s != Moment (0);
115 Paper_column::is_used (Grob *me)
117 extract_grob_set (me, "elements", elts);
121 extract_grob_set (me, "bounded-by-me", bbm);
125 if (Paper_column::is_breakable (me))
128 if (to_boolean (me->get_property ("used")))
134 Paper_column::is_breakable (Grob *me)
136 return scm_is_symbol (me->get_property ("line-break-permission"));
140 Print a vertical line and the rank number, to aid debugging.
142 MAKE_SCHEME_CALLBACK (Paper_column, print, 1);
144 Paper_column::print (SCM p)
146 Paper_column *me = dynamic_cast<Paper_column*> (unsmob_grob (p));
148 string r = to_string (Paper_column::get_rank (me));
150 Moment *mom = unsmob_moment (me->get_property ("when"));
151 string when = mom ? mom->to_string () : "?/?";
153 Font_metric *musfont = Font_interface::get_default_font (me);
154 SCM properties = Font_interface::text_font_alist_chain (me);
156 SCM scm_mol = Text_interface::interpret_markup (me->layout ()->self_scm (),
159 SCM when_mol = Text_interface::interpret_markup (me->layout ()->self_scm (),
161 ly_string2scm (when));
162 Stencil t = *unsmob_stencil (scm_mol);
163 t.add_at_edge (Y_AXIS, DOWN, *unsmob_stencil (when_mol), 0.1, 0.1);
164 t.align_to (X_AXIS, CENTER);
165 t.align_to (Y_AXIS, DOWN);
167 Stencil l = Lookup::filled_box (Box (Interval (-0.01, 0.01),
170 SCM small_letters = scm_cons (scm_acons (ly_symbol2scm ("font-size"),
171 scm_from_int (-6), SCM_EOL),
175 for (SCM s = me->get_object ("ideal-distances");
176 scm_is_pair (s); s = scm_cdr (s))
178 Spring_smob *sp = unsmob_spring (scm_car (s));
182 pts.push_back (Offset (0, y));
184 Offset p2 (sp->distance_, y);
187 Stencil id_stencil = Lookup::points_to_line_stencil (0.1, pts);
188 Stencil head (musfont->find_by_name ("arrowheads.open.01"));
190 SCM distance_stc = Text_interface::interpret_markup (me->layout ()->self_scm (),
192 ly_string2scm (String_convert::form_string ("%5.2lf", sp->distance_)));
194 id_stencil.add_stencil (unsmob_stencil (distance_stc)->translated (Offset (sp->distance_/3, y+1)));
195 id_stencil.add_stencil (head.translated (p2));
196 id_stencil = id_stencil.in_color (0,0,1);
197 l.add_stencil (id_stencil);
200 for (SCM s = me->get_object ("minimum-distances");
201 scm_is_pair (s); s = scm_cdr (s))
203 Real dist = scm_to_double (scm_cdar (s));
205 Real y = -j * 0.1 -3.5;
207 pts.push_back (Offset (0, y));
212 Stencil id_stencil = Lookup::points_to_line_stencil (0.1, pts);
213 Stencil head (musfont->find_by_name ("arrowheads.open.0M1"));
214 head.translate_axis (y, Y_AXIS);
215 id_stencil.add_stencil (head);
217 SCM distance_stc = Text_interface::interpret_markup (me->layout ()->self_scm (),
219 ly_string2scm (String_convert::form_string ("%5.2lf",
222 id_stencil.add_stencil (unsmob_stencil (distance_stc)->translated (Offset (dist/3, y-1)));
225 id_stencil = id_stencil.in_color (1,0,0);
226 l.add_stencil (id_stencil);
229 return t.smobbed_copy ();
233 This is all too hairy. We use bounded-by-me to make sure that some
234 columns are kept "alive". Unfortunately, when spanners are suicided,
235 this falls apart again, because suicided spanners are still in
238 THIS IS BROKEN KLUDGE. WE SHOULD INVENT SOMETHING BETTER.
240 MAKE_SCHEME_CALLBACK (Paper_column, before_line_breaking, 1);
242 Paper_column::before_line_breaking (SCM grob)
244 Grob *me = unsmob_grob (grob);
246 SCM bbm = me->get_object ("bounded-by-me");
247 Grob_array *ga = unsmob_grob_array (bbm);
249 return SCM_UNSPECIFIED;
251 vector<Grob*> &array (ga->array_reference ());
253 for (vsize i = array.size (); i--;)
257 if (!g || !g->is_live ())
258 /* UGH . potentially quadratic. */
259 array.erase (array.begin () + i);
262 return SCM_UNSPECIFIED;
266 ADD_INTERFACE (Paper_column,
267 "@code{Paper_column} objects form the top-most X-parents for items."
268 " The are two types of columns: musical columns, where are attached to, and "
269 " non-musical columns, where bar-lines, clefs etc. are attached to. "
270 " The spacing engine determines the X-positions of these objects."
274 " numbered, the first (leftmost) is column 0. Numbering happens before\n"
275 " line-breaking, and columns are not renumbered after line breaking.\n"
276 " Since many columns go unused, you should only use the rank field to\n"
277 " get ordering information. Two adjacent columns may have\n"
278 " non-adjacent numbers.\n",
285 "line-break-system-details "
286 "line-break-penalty "
287 "line-break-permission "
288 "page-break-penalty "
289 "page-break-permission "
291 "page-turn-permission "
293 "shortest-playing-duration "
294 "shortest-starter-duration "