+ pos
+ = robust_scm2double (me->get_property ("staff-position"), 0);
+
+ /*
+ semibreve rests are positioned one staff line off
+ */
+ if (duration_log == 0)
+ return pos + 2;
+
+ /*
+ trust the client on good positioning;
+ would be tempting to adjust position of rests longer than a quarter
+ to be properly aligned to staff lines,
+ but custom rest shapes may not need that sort of care.
+ */
+
+ return pos;
+ }
+
+ Real vpos = dir * robust_scm2int (me->get_property ("voiced-position"), 0);
+ pos = vpos;
+
+ if (duration_log > 1)
+ /* Only half notes or longer want alignment with staff lines */
+ return pos;
+
+ /*
+ We need a staff symbol for actually aligning anything
+ */
+ Grob *staff = Staff_symbol_referencer::get_staff_symbol (me);
+ if (!staff)
+ return pos;
+
+ std::vector<Real> linepos = Staff_symbol::line_positions (staff);
+
+ if (linepos.empty ())
+ return pos;
+
+ std::sort (linepos.begin (), linepos.end ());
+
+ if (duration_log == 0)
+ {
+ /*
+ lower voice semibreve rests generally hang a line lower
+ */
+
+ if (dir < 0)
+ pos -= 2;
+
+ /*
+ make a semibreve rest hang from the next available line,
+ except when there is none.
+ */
+
+ std::vector<Real>::const_iterator it
+ = std::upper_bound (linepos.begin (), linepos.end (), pos);
+ if (it != linepos.end ())
+ pos = *it;
+ else
+ pos = linepos.back ();