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"
17 #include "directional-element-interface.hh"
22 set_manual_tie_configuration (Array<Tie_configuration> *tie_configs,
23 bool *manual_override,
27 *manual_override = false;
29 for (SCM s = manual_configs;
30 scm_is_pair (s) && k < tie_configs->size(); s = scm_cdr (s))
32 SCM entry = scm_car (s);
33 if (!scm_is_pair (entry))
36 *manual_override = true;
37 Tie_configuration &conf = tie_configs->elem_ref (k);
39 Real complete_pos = robust_scm2double (scm_car (entry),
42 conf.position_ = int (rint (complete_pos));
43 conf.delta_y_ = complete_pos - conf.position_;
44 conf.dir_ = Direction (robust_scm2int (scm_cdr (entry),
51 set_chord_outline (Array<Skyline_entry> *skyline,
52 Link_array<Item> bounds,
56 Real staff_space = Staff_symbol_referencer::staff_space (bounds[0]);
62 for (int i = 0; i < bounds.size (); i++)
64 Grob *head = bounds[i];
65 if (!Note_head::has_interface (head))
69 stem = unsmob_grob (head->get_object ("stem"));
71 Real p = Staff_symbol_referencer::get_position (head);
72 Interval y ((p-1) * 0.5 * staff_space,
73 (p+1) * 0.5 * staff_space);
75 Interval x = head->extent (common, X_AXIS);
76 boxes.push (Box (x, y));
80 (*skyline) = empty_skyline (-d);
82 if (bounds[0]->break_status_dir ())
84 Real x = robust_relative_extent (bounds[0], common, X_AXIS)[-d];
85 skyline->elem_ref (0).height_ = x;
88 for (int i = 0; i < boxes.size (); i++)
89 insert_extent_into_skyline (skyline,
90 boxes[i], Y_AXIS, -d);
92 && !Stem::is_invisible (stem))
95 x.add_point (stem->relative_coordinate (common, X_AXIS));
96 x.widen (staff_space / 20); // ugh.
98 y.add_point (Stem::stem_end_position (stem) * staff_space * .5);
100 Direction stemdir = get_grob_direction (stem);
101 y.add_point (Stem::head_positions (stem)[-stemdir]
104 insert_extent_into_skyline (skyline, Box (x,y), Y_AXIS, -d);
110 Box flag_box = Stem::get_translated_flag (stem).extent_box ();
111 flag_box.translate( Offset (x[RIGHT], X_AXIS));
112 insert_extent_into_skyline (skyline, flag_box,
117 Direction updowndir = DOWN;
124 Box b = boxes.boundary (updowndir, 0);
126 x[-d] = b[X_AXIS].linear_combination (-d / 2);
127 y[-updowndir] = b[Y_AXIS][updowndir];
128 y[updowndir] = updowndir * infinity_f;
132 insert_extent_into_skyline (skyline,
136 while (flip (&updowndir) != DOWN);
138 for (int i = 0; i < bounds.size (); i++)
140 if (!Note_head::has_interface (bounds[i]))
144 Grob *dots = unsmob_grob (bounds[i]->get_object ("dot"));
145 if (dots && d == LEFT)
147 Interval x = dots->extent (common, X_AXIS);
148 Real p = Staff_symbol_referencer::get_position (dots);
151 y *= (staff_space /4);
152 y.translate (p * staff_space * .5);
154 insert_extent_into_skyline (skyline,
155 Box (x,y), Y_AXIS, -d);
161 set_chord_outlines (Drul_array< Array<Skyline_entry> > *skyline_drul,
162 Link_array<Grob> ties,
169 Link_array<Item> bounds;
171 for (int i = 0; i < ties.size (); i++)
173 Item *it = dynamic_cast<Spanner*> (ties[i])->get_bound (d);
178 set_chord_outline (&skyline_drul->elem_ref (d),
181 while (flip (&d) != LEFT);
185 shift_small_ties (Array<Tie_configuration> *tie_configs,
186 Grob *staff_referencer,
187 Tie_details const &details)
189 set<int> positions_taken;
190 for (int i = 0; i < tie_configs->size (); i++)
191 positions_taken.insert (int (rint (tie_configs->elem (i).position_)));
193 for (int i = 0; i < tie_configs->size (); i++)
195 Tie_configuration * conf = &tie_configs->elem_ref (i);
198 on staff line and small enough, translate a little further
200 Real h = conf->height (details);
201 bool next_free = positions_taken.find (int (rint (conf->position_ + conf->dir_)))
202 == positions_taken.end ();
204 int rounded_pos = int (rint (conf->position_ + conf->delta_y_ / details.staff_space_));
205 bool on_line = Staff_symbol_referencer::on_staffline (staff_referencer, rounded_pos);
208 if (on_line && h < 0.4 * details.staff_space_)
210 positions_taken.insert (int (rint (conf->position_ + conf->dir_)));
211 conf->delta_y_ += 0.2 * details.staff_space_ * conf->dir_;
213 else if (!on_line && h > 0.6 * details.staff_space_)
215 positions_taken.insert (int (rint (conf->position_ + conf->dir_)));
216 conf->delta_y_ += 0.5 * details.staff_space_ * conf->dir_;
223 final_shape_adjustment (Tie_configuration &conf,
224 Drul_array< Array<Skyline_entry> > const &skylines,
225 Grob *staff_referencer,
226 Tie_details const &details)
229 bool on_line = Staff_symbol_referencer::on_staffline (staff_referencer,
230 int (rint (conf.position_)));
232 line_dy = - sign (conf.height (details) - 0.6 * details.staff_space_)
233 * 0.2 * details.staff_space_ * conf.dir_;
235 Real y = conf.position_ * details.staff_space_ * 0.5
238 conf.attachment_x_ = get_skyline_attachment (skylines, y);
239 conf.attachment_x_.intersect (get_skyline_attachment (skylines,
240 y + conf.dir_ * details.staff_space_ * 0.5));
242 conf.delta_y_ += line_dy;
243 conf.attachment_x_.widen (-details.x_gap_);
245 && Staff_symbol_referencer::staff_radius (staff_referencer) * details.staff_space_ > y)
246 conf.center_tie_vertically (details);
250 set_tie_config_directions (Array<Tie_configuration> *tie_configs_ptr)
252 Array<Tie_configuration> &tie_configs (*tie_configs_ptr);
254 if (!tie_configs[0].dir_)
255 tie_configs[0].dir_ = DOWN;
256 if (!tie_configs.top().dir_)
257 tie_configs.top().dir_ = UP;
262 for (int i = 1; i < tie_configs.size(); i++)
264 Real diff = tie_configs[i-1].position_ - tie_configs[i].position_;
265 if (fabs (diff) <= 1)
267 if (!tie_configs[i-1].dir_)
268 tie_configs[i-1].dir_ = DOWN;
269 if (!tie_configs[i].dir_)
270 tie_configs[i].dir_ = UP;
274 for (int i = 1; i < tie_configs.size() - 1; i++)
276 if (tie_configs[i].dir_)
279 Direction position_dir = (Direction) sign (tie_configs[i].position_);
283 tie_configs[i].dir_ = position_dir;