#include "tie-column.hh"
#include <math.h>
-
#include <map>
#include <set>
-
-#include "stencil.hh"
+#include "note-head.hh"
#include "stem.hh"
#include "skyline.hh"
#include "staff-symbol-referencer.hh"
}
-
void
-set_chord_outlines (Drul_array< Array<Skyline_entry> > *skyline_drul,
- Link_array<Grob> ties,
- Grob *common)
+set_chord_outline (Array<Skyline_entry> *skyline,
+ Link_array<Item> bounds,
+ Grob *common,
+ Direction d)
{
- Direction d = LEFT;
+ Real staff_space = Staff_symbol_referencer::staff_space (bounds[0]);
- Real staff_space = Staff_symbol_referencer::staff_space (ties[0]);
- do
+ Array<Box> boxes;
+ Interval x_union;
+
+ Grob *stem = 0;
+ for (int i = 0; i < bounds.size (); i++)
{
- Array<Box> boxes;
- Interval x_union;
+ Grob *head = bounds[i];
+ if (!Note_head::has_interface (head))
+ continue;
+
+ if (!stem)
+ stem = unsmob_grob (head->get_object ("stem"));
+
+ Real p = Staff_symbol_referencer::get_position (head);
+ Interval y ((p-1) * 0.5 * staff_space,
+ (p+1) * 0.5 * staff_space);
- Grob *stem = 0;
- for (int i = 0; i < ties.size (); i++)
- {
- Spanner *tie = dynamic_cast<Spanner*> (ties[i]);
+ Interval x = head->extent (common, X_AXIS);
+ boxes.push (Box (x, y));
+ x_union.unite (x);
+ }
- Grob *head = Tie::head (tie, d);
- if (!head)
- continue;
+ (*skyline) = empty_skyline (-d);
- if (!stem)
- stem = unsmob_grob (head->get_object ("stem"));
+ if (bounds[0]->break_status_dir ())
+ {
+ Real x = robust_relative_extent (bounds[0], common, X_AXIS)[-d];
+ skyline->elem_ref (0).height_ = x;
+ }
+
+ for (int i = 0; i < boxes.size (); i++)
+ insert_extent_into_skyline (skyline,
+ boxes[i], Y_AXIS, -d);
+ if (stem
+ && !Stem::is_invisible (stem))
+ {
+ Interval x;
+ x.add_point (stem->relative_coordinate (common, X_AXIS));
+ x.widen (staff_space / 20); // ugh.
+ Interval y;
+ y.add_point (Stem::stem_end_position (stem) * staff_space * .5);
+
+ Direction stemdir = Stem::get_direction (stem);
+ y.add_point (Stem::head_positions (stem)[-stemdir]
+ * staff_space * .5);
- Real p = Tie::get_position (tie);
- Interval y ((p-1) * 0.5 * staff_space,
- (p+1) * 0.5 * staff_space);
+ insert_extent_into_skyline (skyline, Box (x,y), Y_AXIS, -d);
+
+
- Interval x = head->extent (common, X_AXIS);
- boxes.push (Box (x, y));
- x_union.unite (x);
+ if (d == LEFT)
+ {
+ Box flag_box = Stem::get_translated_flag (stem).extent_box ();
+ flag_box.translate( Offset (x[RIGHT], X_AXIS));
+ insert_extent_into_skyline (skyline, flag_box,
+ Y_AXIS, -d);
+ }
+ }
+
+ Direction updowndir = DOWN;
+ do
+ {
+ Interval x ;
+ Interval y;
+ if (boxes.size())
+ {
+ Box b = boxes.boundary (updowndir, 0);
+ x = b[X_AXIS];
+ x[-d] = b[X_AXIS].linear_combination (-d / 2);
+ y[-updowndir] = b[Y_AXIS][updowndir];
+ y[updowndir] = updowndir * infinity_f;
}
- (*skyline_drul)[d] = empty_skyline (-d);
+ if (!x.is_empty ())
+ insert_extent_into_skyline (skyline,
+ Box (x,y),
+ Y_AXIS, -d);
+ }
+ while (flip (&updowndir) != DOWN);
+
+ for (int i = 0; i < bounds.size (); i++)
+ {
+ if (!Note_head::has_interface (bounds[i]))
+ continue;
+
- Spanner *tie = dynamic_cast<Spanner*> (ties[0]);
- if (tie->get_bound (d)->break_status_dir ())
+ Grob *dots = unsmob_grob (bounds[i]->get_object ("dot"));
+ if (dots && d == LEFT)
{
- Real x = robust_relative_extent (tie->get_bound (d),
- common,
- X_AXIS)[-d];
+ Interval x = dots->extent (common, X_AXIS);
+ Real p = Staff_symbol_referencer::get_position (dots);
+
+ Interval y (-1,1);
+ y *= (staff_space /4);
+ y.translate (p * staff_space * .5);
- (*skyline_drul)[d].elem_ref (0).height_ = x;
+ insert_extent_into_skyline (skyline,
+ Box (x,y), Y_AXIS, -d);
}
-
- for (int i = 0; i < boxes.size (); i++)
- insert_extent_into_skyline (&skyline_drul->elem_ref (d),
- boxes[i], Y_AXIS, -d);
- if (stem
- && !Stem::is_invisible (stem))
+ }
+}
+
+void
+set_chord_outlines (Drul_array< Array<Skyline_entry> > *skyline_drul,
+ Link_array<Grob> ties,
+ Grob *common)
+{
+ Direction d = LEFT;
+
+ do
+ {
+ Link_array<Item> bounds;
+
+ for (int i = 0; i < ties.size (); i++)
{
- Interval x;
- x.add_point (stem->relative_coordinate (common, X_AXIS));
- x.widen (staff_space / 20); // ugh.
- Interval y;
- y.add_point (Stem::stem_end_position (stem) * staff_space * .5);
-
- Direction stemdir = Stem::get_direction (stem);
- y.add_point (Stem::head_positions (stem)[-stemdir]
- * staff_space * .5);
-
- insert_extent_into_skyline (&skyline_drul->elem_ref (d),
- Box (x,y), Y_AXIS, -d);
+ Item *it = dynamic_cast<Spanner*> (ties[i])->get_bound (d);
+
+ bounds.push (it);
+ }
+
+ set_chord_outline (&skyline_drul->elem_ref (d),
+ bounds, common, d);
+ }
+ while (flip (&d) != LEFT);
+}
+void
+shift_small_ties (Array<Tie_configuration> *tie_configs,
+ Grob *staff_referencer,
+ Tie_details const &details)
+{
+ set<int> positions_taken;
+ for (int i = 0; i < tie_configs->size (); i++)
+ positions_taken.insert (int (rint (tie_configs->elem (i).position_)));
+ for (int i = 0; i < tie_configs->size (); i++)
+ {
+ Tie_configuration * conf = &tie_configs->elem_ref (i);
- if (d == LEFT)
- {
- Box flag_box = Stem::get_translated_flag (stem).extent_box ();
- flag_box.translate( Offset (x[RIGHT], X_AXIS));
- insert_extent_into_skyline (&skyline_drul->elem_ref (d),
- flag_box,
- Y_AXIS, -d);
- }
- }
+ /*
+ on staff line and small enough, translate a little further
+ */
+ Real h = conf->height (details);
+ bool next_free = positions_taken.find (int (rint (conf->position_ + conf->dir_)))
+ == positions_taken.end ();
+ int rounded_pos = int (rint (conf->position_ + conf->delta_y_ / details.staff_space_));
+ bool on_line = Staff_symbol_referencer::on_staffline (staff_referencer, rounded_pos);
+ if (next_free)
+ if (on_line && h < 0.4 * details.staff_space_)
+ {
+ positions_taken.insert (int (rint (conf->position_ + conf->dir_)));
+ conf->delta_y_ += 0.2 * details.staff_space_ * conf->dir_;
+ }
+ else if (!on_line && h > 0.6 * details.staff_space_)
+ {
+ positions_taken.insert (int (rint (conf->position_ + conf->dir_)));
+ conf->delta_y_ += 0.5 * details.staff_space_ * conf->dir_;
+ }
+ }
+}
- Direction updowndir = DOWN;
- do
+void
+final_shape_adjustment (Tie_configuration &conf,
+ Drul_array< Array<Skyline_entry> > const &skylines,
+ Grob *staff_referencer,
+ Tie_details const &details)
+{
+ Real line_dy = 0.0;
+ bool on_line = Staff_symbol_referencer::on_staffline (staff_referencer,
+ int (rint (conf.position_)));
+ if (on_line)
+ line_dy = - sign (conf.height (details) - 0.6 * details.staff_space_)
+ * 0.2 * details.staff_space_ * conf.dir_;
+
+ Real y = conf.position_ * details.staff_space_ * 0.5
+ + line_dy;
+
+ conf.attachment_x_ = get_skyline_attachment (skylines, y);
+ conf.attachment_x_.intersect (get_skyline_attachment (skylines,
+ y + conf.dir_ * details.staff_space_ * 0.5));
+
+ conf.delta_y_ += line_dy;
+ conf.attachment_x_.widen (-details.x_gap_);
+ if (!on_line
+ && Staff_symbol_referencer::staff_radius (staff_referencer) * details.staff_space_ > y)
+ conf.center_tie_vertically (details);
+}
+
+void
+set_tie_config_directions (Array<Tie_configuration> *tie_configs_ptr)
+{
+ Array<Tie_configuration> &tie_configs (*tie_configs_ptr);
+
+ if (!tie_configs[0].dir_)
+ tie_configs[0].dir_ = DOWN;
+ if (!tie_configs.top().dir_)
+ tie_configs.top().dir_ = UP;
+
+ /*
+ Seconds
+ */
+ for (int i = 1; i < tie_configs.size(); i++)
+ {
+ if (fabs (tie_configs[i-1].position_ - tie_configs[i].position_) <= 1)
{
- Interval x ;
- Interval y;
- if (boxes.size())
- {
- Box b = boxes.boundary (updowndir, 0);
- x = b[X_AXIS];
- x[-d] = b[X_AXIS].linear_combination (-d / 2);
- y[-updowndir] = b[Y_AXIS][updowndir];
- y[updowndir] = updowndir * infinity_f;
- }
-
- if (!x.is_empty ())
- insert_extent_into_skyline (&skyline_drul->elem_ref (d),
- Box (x,y),
- Y_AXIS, -d);
+ if (!tie_configs[i-1].dir_)
+ tie_configs[i-1].dir_ = DOWN;
+ if (!tie_configs[i].dir_)
+ tie_configs[i].dir_ = UP;
}
- while (flip (&updowndir) != DOWN);
+ }
- for (int i = 0; i < ties.size (); i++)
- {
- Spanner *tie = dynamic_cast<Spanner*> (ties[i]);
- Grob *head = Tie::head (tie, d);
- if (!head)
- continue;
-
- Grob *dots = unsmob_grob (head->get_object ("dot"));
- if (dots && d == LEFT)
- {
- Interval x = dots->extent (common, X_AXIS);
- Real p = Staff_symbol_referencer::get_position (dots);
-
- Interval y (-1,1);
- y *= (staff_space /4);
- y.translate (p * staff_space * .5);
+ for (int i = 1; i < tie_configs.size() - 1; i++)
+ {
+ if (tie_configs[i].dir_)
+ continue;
- insert_extent_into_skyline (&skyline_drul->elem_ref (d),
- Box (x,y), Y_AXIS, -d);
- }
- }
+ Direction position_dir = (Direction) sign (tie_configs[i].position_);
+ if (!position_dir)
+ position_dir = DOWN;
+ tie_configs[i].dir_ = position_dir;
}
- while (flip (&d) != LEFT);
}
-
+
void
Tie_column::new_directions (Grob *me)
continue;
manual_override = true;
- tie_configs[k].position_ = robust_scm2double (scm_car (entry), tie_configs[k].position_);
+ Real complete_pos = robust_scm2double (scm_car (entry), tie_configs[k].position_);
+
+ tie_configs[k].position_ = int (rint (complete_pos));
+ tie_configs[k].delta_y_ = complete_pos - tie_configs[k].position_;
tie_configs[k].dir_ = Direction (robust_scm2int (scm_cdr (entry), tie_configs[k].dir_));
k ++;
}
- if (!tie_configs[0].dir_)
- tie_configs[0].dir_ = DOWN;
- if (!tie_configs.top().dir_)
- tie_configs.top().dir_ = UP;
-
- /*
- Seconds
- */
- for (int i = 1; i < tie_configs.size(); i++)
- {
- if (fabs (tie_configs[i-1].position_ - tie_configs[i].position_) <= 1)
- {
- if (!tie_configs[i-1].dir_)
- tie_configs[i-1].dir_ = DOWN;
- if (!tie_configs[i].dir_)
- tie_configs[i].dir_ = UP;
- }
- }
-
- for (int i = 1; i < tie_configs.size() - 1; i++)
- {
- if (tie_configs[i].dir_)
- continue;
-
- Direction position_dir = (Direction) sign (tie_configs[i].position_);
- if (!position_dir)
- position_dir = DOWN;
-
- tie_configs[i].dir_ = position_dir;
- }
+ set_tie_config_directions (&tie_configs);
Grob *common = me;
for (int i = 0; i < ties.size (); i++)
/*
Calculate final width and shape of the ties.
*/
- Real staff_space = Staff_symbol_referencer::staff_space (ties[0]);
- Real gap = robust_scm2double (ties[0]->get_property ("x-gap"), 0.2);
for (int i = 0; i < ties.size(); i++)
{
if (!manual_override
&& (i == 0 || i == ties.size () -1))
continue;
-
- Tie_configuration conf = tie_configs[i];
- conf = tie_configs[i];
-
- Real line_dy = 0.0;
- bool on_line = Staff_symbol_referencer::on_staffline (ties[0],
- int (rint (conf.position_)));
- if (on_line)
- line_dy = - sign (conf.height (details) - 0.6 * staff_space)
- * 0.2 * staff_space * conf.dir_;
-
- Real y = conf.position_ * staff_space * 0.5
- + line_dy;
- conf.attachment_x_
- = get_skyline_attachment (skylines, y);
- conf.attachment_x_.intersect (get_skyline_attachment (skylines,
- y + conf.dir_ * staff_space * .5));
-
-
- conf.delta_y_ += line_dy;
- conf.attachment_x_.widen (-gap);
- if (!on_line
- && Staff_symbol_referencer::staff_radius (ties[0]) * staff_space > y)
- conf.center_tie_vertically (details);
-
- tie_configs[i] = conf;
+
+
+ final_shape_adjustment (tie_configs[i],
+ skylines,
+ ties[0],
+ details);
}
+
/*
Try to shift small ties into available spaces.
*/
if (!manual_override)
{
- set<int> positions_taken;
- for (int i = 0; i < tie_configs.size (); i++)
- positions_taken.insert (int (rint (tie_configs[i].position_)));
-
- for (int i = 0; i < tie_configs.size (); i++)
- {
- Tie_configuration * conf = &tie_configs.elem_ref (i);
-
- /*
- on staff line and small enough, translate a little further
- */
- Real h = conf->height (details);
- bool next_free = positions_taken.find (int (rint (conf->position_ + conf->dir_)))
- == positions_taken.end ();
- bool on_line = Staff_symbol_referencer::on_staffline (ties[0],
- int (rint (conf->position_ + conf->delta_y_)));
- if (next_free)
- if (on_line && h < 0.4 * staff_space)
- {
- positions_taken.insert (int (rint (conf->position_ + conf->dir_)));
- conf->delta_y_ += 0.2 * staff_space * conf->dir_;
- }
- else if (!on_line && h > 0.6 * staff_space)
- {
- positions_taken.insert (int (rint (conf->position_ + conf->dir_)));
- conf->delta_y_ += 0.5 * staff_space * conf->dir_;
- }
- }
+ shift_small_ties (&tie_configs, ties[0], details);
}
for (int i = 0; i < ties.size(); i++)
ADD_INTERFACE (Tie_column, "tie-column-interface",
"Object that sets directions of multiple ties in a tied chord",
+
+ /* properties */
"positioning-done "
"tie-configuration "
);
/*
UGH. Don't mirror Tie_configuration.
*/
- Direction dir = CENTER;
-
- int tie_position = (int) Tie::get_position (me);
- int staff_position = (int) conf->position_;
-
- if (conf->dir_)
- {
- dir = conf->dir_;
- }
- else
- {
- dir = get_grob_direction (me);
- if (!dir)
- dir = get_default_dir (me);
- }
+ conf->head_position_ = (int) Tie::get_position (me);
+ if (!conf->dir_)
+ conf->dir_ = get_grob_direction (me);
+ if (!conf->dir_)
+ conf->dir_ = get_default_dir (me);
+
Real staff_space = details.staff_space_;
-
bool in_between = true;
- Interval attachments = conf->attachment_x_;
Real gap = robust_scm2double (me->get_property ("x-gap"), 0.2);
- if (attachments.is_empty())
+
+ if (conf->attachment_x_.is_empty())
{
if (!skylines)
- attachments = get_default_attachments (me, common, gap,
- &staff_position,
+ conf->attachment_x_ = get_default_attachments (me, common, gap,
+ &conf->position_,
&in_between);
else
{
- Real y = staff_space * 0.5 * staff_position;
- attachments = get_skyline_attachment (*skylines, y);
- attachments.widen (-gap);
+ Real y = staff_space * 0.5 * conf->position_;
+ conf->attachment_x_ = get_skyline_attachment (*skylines, y);
+ conf->attachment_x_.widen (-gap);
}
}
- Bezier b = slur_shape (attachments.length(),
+ Bezier b = slur_shape (conf->attachment_x_.length(),
details.height_limit_,
details.ratio_);
- b.scale (1, dir);
+ b.scale (1, conf->dir_);
Offset middle = b.curve_point (0.5);
Offset edge = b.curve_point (0.0);
- staff_position = int (rint (staff_position));
+ conf->position_ = int (rint (conf->position_));
Real dy = fabs (middle[Y_AXIS] - edge[Y_AXIS]);
- bool in_space = !(Staff_symbol_referencer::on_staffline (me, (int) staff_position));
+ bool in_space = !(Staff_symbol_referencer::on_staffline (me, (int) conf->position_));
bool fits_in_space =
(dy < 0.6 * staff_space);
? int (Staff_symbol_referencer::get_position (left_dot))
: 0;
if (left_dot
- && (staff_position == dot_pos
- || staff_position + dir == dot_pos))
+ && (conf->position_ == dot_pos
+ || conf->position_ + conf->dir_ == dot_pos))
{
- staff_position += dir;
+ conf->position_ += conf->dir_;
in_space = !in_space;
if (skylines)
{
- Real y = staff_space * 0.5 * staff_position;
- attachments = get_skyline_attachment (*skylines, y);
- attachments.widen (-gap);
- Bezier b = slur_shape (attachments.length(),
+ Real y = staff_space * 0.5 * conf->position_;
+ conf->attachment_x_ = get_skyline_attachment (*skylines, y);
+ conf->attachment_x_.widen (-gap);
+ Bezier b = slur_shape (conf->attachment_x_.length(),
details.height_limit_,
details.ratio_);
Offset middle = b.curve_point (0.5);
if (left_stem)
{
Stencil flag = Stem::get_translated_flag (left_stem);
- Real y = staff_position * staff_space * 0.5;
+ Real y = conf->position_ * staff_space * 0.5;
if (flag.extent (Y_AXIS).contains (y))
{
- staff_position += dir;
+ conf->position_ += conf->dir_;
in_space = !in_space;
}
}
{
if (in_space)
{
- staff_position += dir;
+ conf->position_ += conf->dir_;
}
else
{
in_space = true;
- staff_position += dir;
+ conf->position_ += conf->dir_;
}
/*
*/
if (skylines)
{
- Real y = staff_space * 0.5 * staff_position;
- attachments = get_skyline_attachment (*skylines, y);
- attachments.widen (-gap);
+ Real y = staff_space * 0.5 * conf->position_;
+ conf->attachment_x_ = get_skyline_attachment (*skylines, y);
+ conf->attachment_x_.widen (-gap);
- Bezier b = slur_shape (attachments.length(),
+ Bezier b = slur_shape (conf->attachment_x_.length(),
details.height_limit_,
details.ratio_);
Offset middle = b.curve_point (0.5);
Putting larger in-space ties next to the notes forces
the edges to be opposite (Y-wise) to the tie direction.
*/
- if (staff_position == tie_position
+ if (conf->position_ == conf->head_position_
&& in_space
- && Staff_symbol_referencer::staff_radius (me) > fabs (staff_position) / 2
+ && Staff_symbol_referencer::staff_radius (me) > fabs (conf->position_) / 2
&& dy > 0.3 * staff_space)
{
- staff_position += 2 * dir;
+ conf->position_ += 2 * conf->dir_;
}
if (!in_between
&& in_space
- && fabs (staff_position - tie_position) <= 1)
- staff_position += 2*dir;
+ && fabs (conf->position_ - conf->head_position_) <= 1)
+ conf->position_ += 2*conf->dir_;
- conf->dir_ = dir;
- conf->position_ = staff_position;
if (in_space)
{
- if ((fabs (staff_position - tie_position) <= 1
+ if ((fabs (conf->position_ - conf->head_position_) <= 1
&& fabs (dy) < 0.45 * staff_space)
|| fabs (dy) < 0.6 * staff_space)
{
/*
vertically center in space.
*/
- conf->dir_ = dir;
- conf->position_ = staff_position;
- conf->attachment_x_ = attachments;
conf->center_tie_vertically (details);
}
else
{
conf->delta_y_ =
- dir * staff_space * (- 0.3);
+ conf->dir_ * staff_space * (- 0.3);
}
}
else
{
- Real where = 0.5 * dir;
+ Real where = 0.5 * conf->dir_;
Real rounding_dy = (where - middle[Y_AXIS]);
conf->delta_y_ = rounding_dy;
- if (dir * (b.curve_point (0.0)[Y_AXIS]
+ if (conf->dir_ * (b.curve_point (0.0)[Y_AXIS]
+ conf->position_ * staff_space * 0.5
+ conf->delta_y_) <
- dir * tie_position * 0.5 * staff_space)
+ conf->dir_ * conf->head_position_ * 0.5 * staff_space)
{
- if (Staff_symbol_referencer::staff_radius (me) > fabs (tie_position) / 2)
- conf->position_ += 2 * dir;
+ if (Staff_symbol_referencer::staff_radius (me) > fabs (conf->head_position_) / 2)
+ conf->position_ += 2 * conf->dir_;
else
- conf->position_ += dir;
+ conf->position_ += conf->dir_;
}
}
if (skylines)
{
Real half_space = 0.5 * staff_space;
- Real y = staff_position * half_space;
+ Real y = conf->position_ * half_space;
- attachments = get_skyline_attachment (*skylines, y);
-
- attachments.widen (-gap);
+ conf->attachment_x_ = get_skyline_attachment (*skylines, y);
+ conf->attachment_x_.widen (-gap);
}
- conf->attachment_x_ = attachments;
}
"tie-interface",
"A tie connecting two noteheads.\n",
-
+
+ /* properties */
"control-points "
"dash-fraction "
"dash-period "