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 skys[RIGHT].merge (Separation_item::conditional_skyline (right, left));
157 return max (0.0, skys[LEFT].distance (skys[RIGHT]));
161 Print a vertical line and the rank number, to aid debugging.
163 MAKE_SCHEME_CALLBACK (Paper_column, print, 1);
165 Paper_column::print (SCM p)
167 Paper_column *me = dynamic_cast<Paper_column*> (unsmob_grob (p));
169 string r = to_string (Paper_column::get_rank (me));
171 Moment *mom = unsmob_moment (me->get_property ("when"));
172 string when = mom ? mom->to_string () : "?/?";
174 Font_metric *musfont = Font_interface::get_default_font (me);
175 SCM properties = Font_interface::text_font_alist_chain (me);
177 SCM scm_mol = Text_interface::interpret_markup (me->layout ()->self_scm (),
180 SCM when_mol = Text_interface::interpret_markup (me->layout ()->self_scm (),
182 ly_string2scm (when));
183 Stencil t = *unsmob_stencil (scm_mol);
184 t.add_at_edge (Y_AXIS, DOWN, *unsmob_stencil (when_mol), 0.1);
185 t.align_to (X_AXIS, CENTER);
186 t.align_to (Y_AXIS, DOWN);
188 Stencil l = Lookup::filled_box (Box (Interval (-0.01, 0.01),
191 SCM small_letters = scm_cons (scm_acons (ly_symbol2scm ("font-size"),
192 scm_from_int (-6), SCM_EOL),
196 for (SCM s = me->get_object ("ideal-distances");
197 scm_is_pair (s); s = scm_cdr (s))
199 Spring *sp = unsmob_spring (scm_caar (s));
200 if (!unsmob_grob (scm_cdar (s))
201 || !unsmob_grob (scm_cdar (s))->get_system ())
207 pts.push_back (Offset (0, y));
209 Offset p2 (sp->distance (), y);
212 Stencil id_stencil = Lookup::points_to_line_stencil (0.1, pts);
213 Stencil head (musfont->find_by_name ("arrowheads.open.01"));
215 SCM distance_stc = Text_interface::interpret_markup (me->layout ()->self_scm (),
217 ly_string2scm (String_convert::form_string ("%5.2lf", sp->distance ())));
219 id_stencil.add_stencil (unsmob_stencil (distance_stc)->translated (Offset (sp->distance ()/3, y+1)));
220 id_stencil.add_stencil (head.translated (p2));
221 id_stencil = id_stencil.in_color (0,0,1);
222 l.add_stencil (id_stencil);
225 for (SCM s = me->get_object ("minimum-distances");
226 scm_is_pair (s); s = scm_cdr (s))
228 Real dist = scm_to_double (scm_cdar (s));
229 Grob *other = unsmob_grob (scm_caar (s));
230 if (!other || other->get_system () != me->get_system ())
235 Real y = -j * 1.0 -3.5;
237 pts.push_back (Offset (0, y));
242 Stencil id_stencil = Lookup::points_to_line_stencil (0.1, pts);
243 Stencil head (musfont->find_by_name ("arrowheads.open.0M1"));
244 head.translate_axis (y, Y_AXIS);
245 id_stencil.add_stencil (head);
247 SCM distance_stc = Text_interface::interpret_markup (me->layout ()->self_scm (),
249 ly_string2scm (String_convert::form_string ("%5.2lf",
252 id_stencil.add_stencil (unsmob_stencil (distance_stc)->translated (Offset (dist/3, y-1)));
255 id_stencil = id_stencil.in_color (1,0,0);
256 l.add_stencil (id_stencil);
259 return t.smobbed_copy ();
263 This is all too hairy. We use bounded-by-me to make sure that some
264 columns are kept "alive". Unfortunately, when spanners are suicided,
265 this falls apart again, because suicided spanners are still in
268 THIS IS BROKEN KLUDGE. WE SHOULD INVENT SOMETHING BETTER.
270 MAKE_SCHEME_CALLBACK (Paper_column, before_line_breaking, 1);
272 Paper_column::before_line_breaking (SCM grob)
274 Grob *me = unsmob_grob (grob);
276 SCM bbm = me->get_object ("bounded-by-me");
277 Grob_array *ga = unsmob_grob_array (bbm);
279 return SCM_UNSPECIFIED;
281 vector<Grob*> &array (ga->array_reference ());
283 for (vsize i = array.size (); i--;)
287 if (!g || !g->is_live ())
288 /* UGH . potentially quadratic. */
289 array.erase (array.begin () + i);
292 return SCM_UNSPECIFIED;
296 ADD_INTERFACE (Paper_column,
297 "@code{Paper_column} objects form the top-most X-parents for items."
298 " The are two types of columns: musical columns, where are attached to, and "
299 " non-musical columns, where bar-lines, clefs etc. are attached to. "
300 " The spacing engine determines the X-positions of these objects."
304 " numbered, the first (leftmost) is column 0. Numbering happens before\n"
305 " line-breaking, and columns are not renumbered after line breaking.\n"
306 " Since many columns go unused, you should only use the rank field to\n"
307 " get ordering information. Two adjacent columns may have\n"
308 " non-adjacent numbers.\n",
316 "line-break-system-details "
317 "line-break-penalty "
318 "line-break-permission "
319 "page-break-penalty "
320 "page-break-permission "
322 "page-turn-permission "
324 "shortest-playing-duration "
325 "shortest-starter-duration "