2 paper-column.cc -- implement Paper_column
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2007 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 "separation-item.hh"
26 #include "string-convert.hh"
29 Paper_column::clone () const
31 return new Paper_column (*this);
35 Paper_column::do_break_processing ()
37 Item::do_break_processing ();
41 Paper_column::get_rank (Grob const *me)
43 return dynamic_cast<Paper_column const *> (me)->rank_;
47 Paper_column::get_system () const
53 Paper_column::set_system (System *s)
59 Paper_column::get_column () const
61 return (Paper_column *) (this);
64 Paper_column::Paper_column (SCM l)
71 Paper_column::Paper_column (Paper_column const &src)
79 Paper_column::compare (Grob * const &a,
82 return sign (dynamic_cast<Paper_column*> (a)->rank_
83 - dynamic_cast<Paper_column*> (b)->rank_);
87 Paper_column::less_than (Grob *const &a,
90 Paper_column *pa = dynamic_cast<Paper_column*> (a);
91 Paper_column *pb = dynamic_cast<Paper_column*> (b);
93 return pa->rank_ < pb->rank_;
97 Paper_column::when_mom (Grob *me)
99 SCM m = me->get_property ("when");
100 if (Moment *when = unsmob_moment (m))
106 Paper_column::is_musical (Grob *me)
108 SCM m = me->get_property ("shortest-starter-duration");
110 if (unsmob_moment (m))
111 s = *unsmob_moment (m);
112 return s != Moment (0);
116 Paper_column::is_used (Grob *me)
118 extract_grob_set (me, "elements", elts);
122 extract_grob_set (me, "bounded-by-me", bbm);
126 if (Paper_column::is_breakable (me))
129 if (to_boolean (me->get_property ("used")))
135 Paper_column::is_breakable (Grob *me)
137 return scm_is_symbol (me->get_property ("line-break-permission"));
141 Paper_column::minimum_distance (Grob *left, Grob *right)
143 Drul_array<Grob*> cols (left, right);
144 Drul_array<Skyline> skys = Drul_array<Skyline> (Skyline (RIGHT), Skyline (LEFT));
149 extract_grob_set (cols[d], "elements", elts);
151 for (vsize i = 0; i < elts.size (); i++)
152 if (Separation_item::has_interface (elts[i]))
154 Skyline_pair *sp = Skyline_pair::unsmob (elts[i]->get_property ("horizontal-skylines"));
156 skys[d].merge ((*sp)[-d]);
159 while (flip (&d) != LEFT);
161 return min (0.0, skys[LEFT].distance (skys[RIGHT]));
165 Print a vertical line and the rank number, to aid debugging.
167 MAKE_SCHEME_CALLBACK (Paper_column, print, 1);
169 Paper_column::print (SCM p)
171 Paper_column *me = dynamic_cast<Paper_column*> (unsmob_grob (p));
173 string r = to_string (Paper_column::get_rank (me));
175 Moment *mom = unsmob_moment (me->get_property ("when"));
176 string when = mom ? mom->to_string () : "?/?";
178 Font_metric *musfont = Font_interface::get_default_font (me);
179 SCM properties = Font_interface::text_font_alist_chain (me);
181 SCM scm_mol = Text_interface::interpret_markup (me->layout ()->self_scm (),
184 SCM when_mol = Text_interface::interpret_markup (me->layout ()->self_scm (),
186 ly_string2scm (when));
187 Stencil t = *unsmob_stencil (scm_mol);
188 t.add_at_edge (Y_AXIS, DOWN, *unsmob_stencil (when_mol), 0.1);
189 t.align_to (X_AXIS, CENTER);
190 t.align_to (Y_AXIS, DOWN);
192 Stencil l = Lookup::filled_box (Box (Interval (-0.01, 0.01),
195 SCM small_letters = scm_cons (scm_acons (ly_symbol2scm ("font-size"),
196 scm_from_int (-6), SCM_EOL),
200 for (SCM s = me->get_object ("ideal-distances");
201 scm_is_pair (s); s = scm_cdr (s))
203 Spring *sp = unsmob_spring (scm_caar (s));
204 if (!unsmob_grob (scm_cdar (s))
205 || !unsmob_grob (scm_cdar (s))->get_system ())
211 pts.push_back (Offset (0, y));
213 Offset p2 (sp->distance (), y);
216 Stencil id_stencil = Lookup::points_to_line_stencil (0.1, pts);
217 Stencil head (musfont->find_by_name ("arrowheads.open.01"));
219 SCM distance_stc = Text_interface::interpret_markup (me->layout ()->self_scm (),
221 ly_string2scm (String_convert::form_string ("%5.2lf", sp->distance ())));
223 id_stencil.add_stencil (unsmob_stencil (distance_stc)->translated (Offset (sp->distance ()/3, y+1)));
224 id_stencil.add_stencil (head.translated (p2));
225 id_stencil = id_stencil.in_color (0,0,1);
226 l.add_stencil (id_stencil);
229 for (SCM s = me->get_object ("minimum-distances");
230 scm_is_pair (s); s = scm_cdr (s))
232 Real dist = scm_to_double (scm_cdar (s));
233 Grob *other = unsmob_grob (scm_caar (s));
234 if (!other || other->get_system () != me->get_system ())
239 Real y = -j * 1.0 -3.5;
241 pts.push_back (Offset (0, y));
246 Stencil id_stencil = Lookup::points_to_line_stencil (0.1, pts);
247 Stencil head (musfont->find_by_name ("arrowheads.open.0M1"));
248 head.translate_axis (y, Y_AXIS);
249 id_stencil.add_stencil (head);
251 SCM distance_stc = Text_interface::interpret_markup (me->layout ()->self_scm (),
253 ly_string2scm (String_convert::form_string ("%5.2lf",
256 id_stencil.add_stencil (unsmob_stencil (distance_stc)->translated (Offset (dist/3, y-1)));
259 id_stencil = id_stencil.in_color (1,0,0);
260 l.add_stencil (id_stencil);
263 return t.smobbed_copy ();
267 This is all too hairy. We use bounded-by-me to make sure that some
268 columns are kept "alive". Unfortunately, when spanners are suicided,
269 this falls apart again, because suicided spanners are still in
272 THIS IS BROKEN KLUDGE. WE SHOULD INVENT SOMETHING BETTER.
274 MAKE_SCHEME_CALLBACK (Paper_column, before_line_breaking, 1);
276 Paper_column::before_line_breaking (SCM grob)
278 Grob *me = unsmob_grob (grob);
280 SCM bbm = me->get_object ("bounded-by-me");
281 Grob_array *ga = unsmob_grob_array (bbm);
283 return SCM_UNSPECIFIED;
285 vector<Grob*> &array (ga->array_reference ());
287 for (vsize i = array.size (); i--;)
291 if (!g || !g->is_live ())
292 /* UGH . potentially quadratic. */
293 array.erase (array.begin () + i);
296 return SCM_UNSPECIFIED;
300 ADD_INTERFACE (Paper_column,
301 "@code{Paper_column} objects form the top-most X-parents for items."
302 " The are two types of columns: musical columns, where are attached to, and "
303 " non-musical columns, where bar-lines, clefs etc. are attached to. "
304 " The spacing engine determines the X-positions of these objects."
308 " numbered, the first (leftmost) is column 0. Numbering happens before\n"
309 " line-breaking, and columns are not renumbered after line breaking.\n"
310 " Since many columns go unused, you should only use the rank field to\n"
311 " get ordering information. Two adjacent columns may have\n"
312 " non-adjacent numbers.\n",
320 "line-break-system-details "
321 "line-break-penalty "
322 "line-break-permission "
323 "page-break-penalty "
324 "page-break-permission "
326 "page-turn-permission "
328 "shortest-playing-duration "
329 "shortest-starter-duration "