+
+
+
\score{
\context PianoStaff <
\context Staff=one \notes\relative c'{
- \stemUp c4( c \translator Staff=two c )c |
+ \stemUp \slurUp
+ c4( c \translator Staff=two c )c |
\translator Staff=one
- \stemUp c4( c \translator Staff=two c )c |
- \stemUp c4( c \translator Staff=one c )c |
+ \stemUp \slurUp
+ c4( c \translator Staff=two c )c |
+ \stemUp \slurUp
+ c4( c \translator Staff=one c )c |
\translator Staff=two
- \stemUp c4( c \translator Staff=one c )c |
+ \stemUp \slurUp
+ c4( c \translator Staff=one c )c |
\translator Staff=two
- \stemUp c4( \translator Staff=one c c )c |
+ \stemUp \slurUp
+ c4( \translator Staff=one c c )c |
r2
\translator Staff=two
- \stemUp c4( \translator Staff=one c
+ \stemUp \slurUp
+ c4( \translator Staff=one c
\break
c )c
r2
-% \stemDown c4( \translator Staff=two c c \translator Staff=one )c
- \stemDown d4( \translator Staff=two c c \translator Staff=one )d
+% \stemDown \slurDown
+% c4( \translator Staff=two c c \translator Staff=one )c
+ \stemDown \slurDown
+ d4( \translator Staff=two c c \translator Staff=one )d
\translator Staff=two
- \stemUp c4( \translator Staff=one c c \translator Staff=two )c
+ \stemUp \slurUp
+ c4( \translator Staff=one c c \translator Staff=two )c
r1
}
\context Staff=two \notes\relative c'{
return list;
}
+Offset
+Line_spanner::get_broken_offset (Grob *me, Direction dir)
+{
+ Spanner *spanner = dynamic_cast<Spanner*> (me);
+ Item* bound = spanner->get_bound (dir);
+
+ if (!bound->break_status_dir ())
+ {
+ Grob *common[] = {
+ bound->common_refpoint (Staff_symbol_referencer::staff_symbol_l (me),
+ X_AXIS),
+ bound->common_refpoint (Staff_symbol_referencer::staff_symbol_l (me),
+ Y_AXIS)
+ };
+
+ return Offset ( abs (bound->extent (common[X_AXIS], X_AXIS)[-dir]),
+ bound->extent (common[Y_AXIS], Y_AXIS).center ());
+ }
+ return Offset ();
+}
+
+Offset
+Line_spanner::broken_trend_offset (Grob *me, Direction dir)
+{
+ /* A broken line-spaner should maintain the same vertical trend
+ the unbroken line-spanner would have had.
+ From slur */
+ Offset o;
+ if (Spanner *mother = dynamic_cast<Spanner*> (me->original_l_))
+ {
+ for (int i = dir == LEFT ? 0 : mother->broken_into_l_arr_.size () - 1;
+ dir == LEFT ? i < mother->broken_into_l_arr_.size () : i > 0;
+ dir == LEFT ? i++ : i--)
+ {
+ if (mother->broken_into_l_arr_[i - dir] == me)
+ {
+ Grob *neighbour = mother->broken_into_l_arr_[i];
+ Offset neighbour_o = get_broken_offset (neighbour, dir);
+ Offset me_o = get_broken_offset (me, -dir);
+ // Hmm, why not return me_o[X], but recalc in brew_mol?
+ o = Offset (0,
+ (neighbour_o[Y_AXIS]*me_o[X_AXIS]
+ - me_o[Y_AXIS]*neighbour_o[X_AXIS]) * dir /
+ (me_o[X_AXIS] + neighbour_o[X_AXIS]));
+ break;
+ }
+ }
+ }
+ return o;
+}
/*
Line_spanner::brew_molecule (SCM smob)
{
Grob *me= unsmob_grob (smob);
+
Spanner *spanner = dynamic_cast<Spanner*> (me);
+ Item* bound_drul[] = {
+ spanner->get_bound (LEFT),
+ 0,
+ spanner->get_bound (RIGHT)
+ };
+
+ Item** bound = bound_drul + 1;
Grob *common[] = { 0, 0 };
-
- Item *l = spanner->get_bound (LEFT);
- Item *r = spanner->get_bound (RIGHT);
-
- /*
- FIXME: should also do something sensible across line breaks.
- */
- if (l->break_status_dir () || r->break_status_dir ())
- return SCM_EOL;
-
for (Axis a = X_AXIS; a < NO_AXES; a = Axis (a + 1))
{
- common[a] = l->common_refpoint (r, a);
-
- if (!common[a])
- return SCM_EOL;
+ common[a] = bound[LEFT]->common_refpoint (bound[RIGHT], a);
+
+ if (!common[a])
+ return SCM_EOL;
}
- Offset dxy ;
- for (Axis a = X_AXIS; a < NO_AXES; a = Axis (a + 1))
+ Real gap = gh_scm2double (me->get_grob_property ("gap"));
+
+ Offset dxy ;
+ Offset my_off;
+ Offset his_off;
+
+ if (bound[LEFT]->break_status_dir () || bound[RIGHT]->break_status_dir ())
+ /* across line break */
{
- dxy[a] = r->extent (common[a], a)[LEFT] -
- l->extent (common[a], a)[RIGHT];
+ Direction broken = bound[LEFT]->break_status_dir () ? LEFT : RIGHT;
+
+ dxy[X_AXIS] = bound[RIGHT]->extent (common[X_AXIS], X_AXIS)[LEFT]
+ - bound[LEFT]->extent (common[X_AXIS], X_AXIS)[RIGHT];
+
+ dxy += broken_trend_offset (me, broken);
+ dxy[X_AXIS] -= 1 * gap;
+
+ my_off = Offset (0,
+ me->relative_coordinate (common[Y_AXIS], Y_AXIS));
+
+ his_off = Offset (0,
+ bound[-broken]->relative_coordinate (common[Y_AXIS],
+ Y_AXIS));
+
+ if (broken == LEFT)
+ {
+ my_off[Y_AXIS] += dxy[Y_AXIS];
+ }
}
-
+ else
+ {
+ dxy[X_AXIS] = bound[RIGHT]->extent (common[X_AXIS], X_AXIS)[LEFT]
+ - bound[LEFT]->extent (common[X_AXIS], X_AXIS)[RIGHT];
+ dxy[Y_AXIS] = bound[RIGHT]->extent (common[Y_AXIS], Y_AXIS).center ()
+ - bound[LEFT]->extent (common[Y_AXIS], Y_AXIS).center ();
+ dxy[X_AXIS] -= 2 * gap;
+
+ my_off = Offset (me->relative_coordinate (common[X_AXIS], X_AXIS),
+ me->relative_coordinate (common[Y_AXIS], Y_AXIS));
+
+ his_off = Offset (bound[LEFT]->relative_coordinate (common[X_AXIS],
+ X_AXIS),
+ bound[LEFT]->relative_coordinate (common[Y_AXIS],
+ Y_AXIS));
+
+ }
Molecule line;
- Real gap = gh_scm2double (me->get_grob_property ("gap"));
-
- Offset my_off(me->relative_coordinate (common[X_AXIS], X_AXIS),
- me->relative_coordinate (common[Y_AXIS], Y_AXIS) );
-
- Offset his_off(l->relative_coordinate (common[X_AXIS], X_AXIS),
- l->relative_coordinate (common[Y_AXIS], Y_AXIS) );
-
- dxy *= (dxy.length () - 2 * gap) / dxy.length ();
-
SCM list = Line_spanner::line_atom (me, dxy[X_AXIS], dxy[Y_AXIS]);
if (list == SCM_EOL)
Box b (Interval (0, dxy[X_AXIS]), Interval (0, dxy[Y_AXIS]));
line = Molecule (b, list);
- line.translate_axis (l->extent (l, X_AXIS).length (), X_AXIS);
-
-
- Offset g = dxy * (gap / dxy.length ());
+ line.translate_axis (bound[LEFT]->extent (bound[LEFT], X_AXIS).length (), X_AXIS);
+
+ Offset g (gap, 0);
line.translate (g - my_off + his_off);
return line.smobbed_copy ();
Request* req_;
Request* last_req_;
Translator* last_staff_;
+ bool follow_;
Grob* head_;
Grob* last_head_;
};
line_ = 0;
req_ = 0;
last_req_ = 0;
+ follow_ = false;
head_ = 0;
last_head_ = 0;
last_staff_ = 0;
if (staff != last_staff_)
{
if (last_head_)
- last_req_ = (Request*)1; // ugh
+ follow_ = true;
last_staff_ = staff;
}
}
void
Note_head_line_engraver::create_grobs ()
{
- if (!line_ && last_req_ && last_head_ && head_)
+ if (!line_ && (follow_ || last_req_) && last_head_ && head_
+ && (last_head_ != head_))
{
/* type Glissando? */
- line_ = new Spanner (get_property ("NoteHeadLine"));
- line_->set_bound (RIGHT, head_);
+ if (follow_)
+ line_ = new Spanner (get_property ("FollowThread"));
+ else
+ line_ = new Spanner (get_property ("Glissando"));
+
line_->set_bound (LEFT, last_head_);
+ line_->set_bound (RIGHT, head_);
- line_->set_parent (head_, X_AXIS);
- line_->set_parent (head_, Y_AXIS);
-
- line_->set_parent (last_head_, X_AXIS);
- line_->set_parent (last_head_, Y_AXIS);
+ /*
+ Note, mustn't set y-parent of breakable symbol to simple item:
+ one of the two broken parts won't have an y-parent!
+
+ line_->set_parent (head_, Y_AXIS);
+ line_->set_parent (last_head_, Y_AXIS);
+
+ */
+ /* X parent is set by set_bound */
+ line_->set_parent (Staff_symbol_referencer::staff_symbol_l (last_head_),
+ Y_AXIS);
- if ((int)last_req_ == 1) // ugh
- last_req_ = 0;
-
announce_grob (line_, last_req_);
last_req_ = 0;
- last_head_ = head_;
- head_ = 0;
+ follow_ = false;
+ last_head_ = 0;
}
}
typeset_grob (line_);
line_ = 0;
}
- if (req_)
- last_req_ = req_;
+ last_req_ = req_;
req_ = 0;
}