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 Skyline_pair *sp = Skyline_pair::unsmob (cols[d]->get_property ("horizontal-skylines"));
153 while (flip (&d) != LEFT);
155 return max (0.0, skys[LEFT].distance (skys[RIGHT]));
159 Print a vertical line and the rank number, to aid debugging.
161 MAKE_SCHEME_CALLBACK (Paper_column, print, 1);
163 Paper_column::print (SCM p)
165 Paper_column *me = dynamic_cast<Paper_column*> (unsmob_grob (p));
167 string r = to_string (Paper_column::get_rank (me));
169 Moment *mom = unsmob_moment (me->get_property ("when"));
170 string when = mom ? mom->to_string () : "?/?";
172 Font_metric *musfont = Font_interface::get_default_font (me);
173 SCM properties = Font_interface::text_font_alist_chain (me);
175 SCM scm_mol = Text_interface::interpret_markup (me->layout ()->self_scm (),
178 SCM when_mol = Text_interface::interpret_markup (me->layout ()->self_scm (),
180 ly_string2scm (when));
181 Stencil t = *unsmob_stencil (scm_mol);
182 t.add_at_edge (Y_AXIS, DOWN, *unsmob_stencil (when_mol), 0.1);
183 t.align_to (X_AXIS, CENTER);
184 t.align_to (Y_AXIS, DOWN);
186 Stencil l = Lookup::filled_box (Box (Interval (-0.01, 0.01),
189 SCM small_letters = scm_cons (scm_acons (ly_symbol2scm ("font-size"),
190 scm_from_int (-6), SCM_EOL),
194 for (SCM s = me->get_object ("ideal-distances");
195 scm_is_pair (s); s = scm_cdr (s))
197 Spring *sp = unsmob_spring (scm_caar (s));
198 if (!unsmob_grob (scm_cdar (s))
199 || !unsmob_grob (scm_cdar (s))->get_system ())
205 pts.push_back (Offset (0, y));
207 Offset p2 (sp->distance (), y);
210 Stencil id_stencil = Lookup::points_to_line_stencil (0.1, pts);
211 Stencil head (musfont->find_by_name ("arrowheads.open.01"));
213 SCM distance_stc = Text_interface::interpret_markup (me->layout ()->self_scm (),
215 ly_string2scm (String_convert::form_string ("%5.2lf", sp->distance ())));
217 id_stencil.add_stencil (unsmob_stencil (distance_stc)->translated (Offset (sp->distance ()/3, y+1)));
218 id_stencil.add_stencil (head.translated (p2));
219 id_stencil = id_stencil.in_color (0,0,1);
220 l.add_stencil (id_stencil);
223 for (SCM s = me->get_object ("minimum-distances");
224 scm_is_pair (s); s = scm_cdr (s))
226 Real dist = scm_to_double (scm_cdar (s));
227 Grob *other = unsmob_grob (scm_caar (s));
228 if (!other || other->get_system () != me->get_system ())
233 Real y = -j * 1.0 -3.5;
235 pts.push_back (Offset (0, y));
240 Stencil id_stencil = Lookup::points_to_line_stencil (0.1, pts);
241 Stencil head (musfont->find_by_name ("arrowheads.open.0M1"));
242 head.translate_axis (y, Y_AXIS);
243 id_stencil.add_stencil (head);
245 SCM distance_stc = Text_interface::interpret_markup (me->layout ()->self_scm (),
247 ly_string2scm (String_convert::form_string ("%5.2lf",
250 id_stencil.add_stencil (unsmob_stencil (distance_stc)->translated (Offset (dist/3, y-1)));
253 id_stencil = id_stencil.in_color (1,0,0);
254 l.add_stencil (id_stencil);
257 return t.smobbed_copy ();
261 This is all too hairy. We use bounded-by-me to make sure that some
262 columns are kept "alive". Unfortunately, when spanners are suicided,
263 this falls apart again, because suicided spanners are still in
266 THIS IS BROKEN KLUDGE. WE SHOULD INVENT SOMETHING BETTER.
268 MAKE_SCHEME_CALLBACK (Paper_column, before_line_breaking, 1);
270 Paper_column::before_line_breaking (SCM grob)
272 Grob *me = unsmob_grob (grob);
274 SCM bbm = me->get_object ("bounded-by-me");
275 Grob_array *ga = unsmob_grob_array (bbm);
277 return SCM_UNSPECIFIED;
279 vector<Grob*> &array (ga->array_reference ());
281 for (vsize i = array.size (); i--;)
285 if (!g || !g->is_live ())
286 /* UGH . potentially quadratic. */
287 array.erase (array.begin () + i);
290 return SCM_UNSPECIFIED;
294 ADD_INTERFACE (Paper_column,
295 "@code{Paper_column} objects form the top-most X-parents for items."
296 " The are two types of columns: musical columns, where are attached to, and "
297 " non-musical columns, where bar-lines, clefs etc. are attached to. "
298 " The spacing engine determines the X-positions of these objects."
302 " numbered, the first (leftmost) is column 0. Numbering happens before\n"
303 " line-breaking, and columns are not renumbered after line breaking.\n"
304 " Since many columns go unused, you should only use the rank field to\n"
305 " get ordering information. Two adjacent columns may have\n"
306 " non-adjacent numbers.\n",
314 "line-break-system-details "
315 "line-break-penalty "
316 "line-break-permission "
317 "page-break-penalty "
318 "page-break-permission "
320 "page-turn-permission "
322 "shortest-playing-duration "
323 "shortest-starter-duration "