2 tie-column-format.cc -- implement formatting routines for Tie_column
4 source file of the GNU LilyPond music typesetter
6 (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
11 #include "note-head.hh"
16 #include "staff-symbol-referencer.hh"
21 set_manual_tie_configuration (Array<Tie_configuration> *tie_configs,
22 bool *manual_override,
26 *manual_override = false;
28 for (SCM s = manual_configs;
29 scm_is_pair (s) && k < tie_configs->size(); s = scm_cdr (s))
31 SCM entry = scm_car (s);
32 if (!scm_is_pair (entry))
35 *manual_override = true;
36 Tie_configuration &conf = tie_configs->elem_ref (k);
38 Real complete_pos = robust_scm2double (scm_car (entry),
41 conf.position_ = int (rint (complete_pos));
42 conf.delta_y_ = complete_pos - conf.position_;
43 conf.dir_ = Direction (robust_scm2int (scm_cdr (entry),
50 set_chord_outline (Array<Skyline_entry> *skyline,
51 Link_array<Item> bounds,
55 Real staff_space = Staff_symbol_referencer::staff_space (bounds[0]);
61 for (int i = 0; i < bounds.size (); i++)
63 Grob *head = bounds[i];
64 if (!Note_head::has_interface (head))
68 stem = unsmob_grob (head->get_object ("stem"));
70 Real p = Staff_symbol_referencer::get_position (head);
71 Interval y ((p-1) * 0.5 * staff_space,
72 (p+1) * 0.5 * staff_space);
74 Interval x = head->extent (common, X_AXIS);
75 boxes.push (Box (x, y));
79 (*skyline) = empty_skyline (-d);
81 if (bounds[0]->break_status_dir ())
83 Real x = robust_relative_extent (bounds[0], common, X_AXIS)[-d];
84 skyline->elem_ref (0).height_ = x;
87 for (int i = 0; i < boxes.size (); i++)
88 insert_extent_into_skyline (skyline,
89 boxes[i], Y_AXIS, -d);
91 && !Stem::is_invisible (stem))
94 x.add_point (stem->relative_coordinate (common, X_AXIS));
95 x.widen (staff_space / 20); // ugh.
97 y.add_point (Stem::stem_end_position (stem) * staff_space * .5);
99 Direction stemdir = Stem::get_direction (stem);
100 y.add_point (Stem::head_positions (stem)[-stemdir]
103 insert_extent_into_skyline (skyline, Box (x,y), Y_AXIS, -d);
109 Box flag_box = Stem::get_translated_flag (stem).extent_box ();
110 flag_box.translate( Offset (x[RIGHT], X_AXIS));
111 insert_extent_into_skyline (skyline, flag_box,
116 Direction updowndir = DOWN;
123 Box b = boxes.boundary (updowndir, 0);
125 x[-d] = b[X_AXIS].linear_combination (-d / 2);
126 y[-updowndir] = b[Y_AXIS][updowndir];
127 y[updowndir] = updowndir * infinity_f;
131 insert_extent_into_skyline (skyline,
135 while (flip (&updowndir) != DOWN);
137 for (int i = 0; i < bounds.size (); i++)
139 if (!Note_head::has_interface (bounds[i]))
143 Grob *dots = unsmob_grob (bounds[i]->get_object ("dot"));
144 if (dots && d == LEFT)
146 Interval x = dots->extent (common, X_AXIS);
147 Real p = Staff_symbol_referencer::get_position (dots);
150 y *= (staff_space /4);
151 y.translate (p * staff_space * .5);
153 insert_extent_into_skyline (skyline,
154 Box (x,y), Y_AXIS, -d);
160 set_chord_outlines (Drul_array< Array<Skyline_entry> > *skyline_drul,
161 Link_array<Grob> ties,
168 Link_array<Item> bounds;
170 for (int i = 0; i < ties.size (); i++)
172 Item *it = dynamic_cast<Spanner*> (ties[i])->get_bound (d);
177 set_chord_outline (&skyline_drul->elem_ref (d),
180 while (flip (&d) != LEFT);
184 shift_small_ties (Array<Tie_configuration> *tie_configs,
185 Grob *staff_referencer,
186 Tie_details const &details)
188 set<int> positions_taken;
189 for (int i = 0; i < tie_configs->size (); i++)
190 positions_taken.insert (int (rint (tie_configs->elem (i).position_)));
192 for (int i = 0; i < tie_configs->size (); i++)
194 Tie_configuration * conf = &tie_configs->elem_ref (i);
197 on staff line and small enough, translate a little further
199 Real h = conf->height (details);
200 bool next_free = positions_taken.find (int (rint (conf->position_ + conf->dir_)))
201 == positions_taken.end ();
203 int rounded_pos = int (rint (conf->position_ + conf->delta_y_ / details.staff_space_));
204 bool on_line = Staff_symbol_referencer::on_staffline (staff_referencer, rounded_pos);
207 if (on_line && h < 0.4 * details.staff_space_)
209 positions_taken.insert (int (rint (conf->position_ + conf->dir_)));
210 conf->delta_y_ += 0.2 * details.staff_space_ * conf->dir_;
212 else if (!on_line && h > 0.6 * details.staff_space_)
214 positions_taken.insert (int (rint (conf->position_ + conf->dir_)));
215 conf->delta_y_ += 0.5 * details.staff_space_ * conf->dir_;
222 final_shape_adjustment (Tie_configuration &conf,
223 Drul_array< Array<Skyline_entry> > const &skylines,
224 Grob *staff_referencer,
225 Tie_details const &details)
228 bool on_line = Staff_symbol_referencer::on_staffline (staff_referencer,
229 int (rint (conf.position_)));
231 line_dy = - sign (conf.height (details) - 0.6 * details.staff_space_)
232 * 0.2 * details.staff_space_ * conf.dir_;
234 Real y = conf.position_ * details.staff_space_ * 0.5
237 conf.attachment_x_ = get_skyline_attachment (skylines, y);
238 conf.attachment_x_.intersect (get_skyline_attachment (skylines,
239 y + conf.dir_ * details.staff_space_ * 0.5));
241 conf.delta_y_ += line_dy;
242 conf.attachment_x_.widen (-details.x_gap_);
244 && Staff_symbol_referencer::staff_radius (staff_referencer) * details.staff_space_ > y)
245 conf.center_tie_vertically (details);
249 set_tie_config_directions (Array<Tie_configuration> *tie_configs_ptr)
251 Array<Tie_configuration> &tie_configs (*tie_configs_ptr);
253 if (!tie_configs[0].dir_)
254 tie_configs[0].dir_ = DOWN;
255 if (!tie_configs.top().dir_)
256 tie_configs.top().dir_ = UP;
261 for (int i = 1; i < tie_configs.size(); i++)
263 if (fabs (tie_configs[i-1].position_ - tie_configs[i].position_) <= 1)
265 if (!tie_configs[i-1].dir_)
266 tie_configs[i-1].dir_ = DOWN;
267 if (!tie_configs[i].dir_)
268 tie_configs[i].dir_ = UP;
272 for (int i = 1; i < tie_configs.size() - 1; i++)
274 if (tie_configs[i].dir_)
277 Direction position_dir = (Direction) sign (tie_configs[i].position_);
281 tie_configs[i].dir_ = position_dir;