- continue;
-
- Direction d = DOWN;
- do
- {
- if (!staff_extent.contains (last->second[d].position_)
- && !staff_extent.contains (i->second[d].position_))
- {
- Real center
- = (last->second[d].head_extent_[RIGHT]
- + i->second[d].head_extent_[LEFT]) / 2;
-
- Direction which = LEFT;
- do
- {
- Ledger_request &lr = ((which == LEFT) ? * last : *i).second[d];
-
- // due tilt of quarter note-heads
- /* FIXME */
- bool both
- = (!staff_extent.contains (last->second[d].position_
- - sign (last->second[d].position_))
- && !staff_extent.contains (i->second[d].position_
- - sign (i->second[d].position_)));
- Real limit = (center + (both ? which * gap / 2 : 0));
- lr.ledger_extent_.at (-which)
- = which * max (which * lr.ledger_extent_[-which], which * limit);
- }
- while (flip (&which) != LEFT);
- }
- }
- while (flip (&d) != DOWN);
+ continue;
+
+ for (DOWN_and_UP (d))
+ {
+ // Some rank--> vdir--> reqs will be 'empty' because notes
+ // will not be above AND below the staff for a given rank.
+ if (!staff_extent.contains (last->second[d].max_position_)
+ && !staff_extent.contains (i->second[d].max_position_))
+ {
+ // Midpoint between the furthest bounds of the two heads.
+ Real center
+ = (last->second[d].max_head_extent_[RIGHT]
+ + i->second[d].max_head_extent_[LEFT]) / 2;
+
+ // Do both reqs have notes further than the first space
+ // beyond the staff?
+ // (due tilt of quarter note-heads)
+ /* FIXME */
+ bool both
+ = (!staff_extent.contains (last->second[d].max_position_
+ - sign (last->second[d].max_position_))
+ && !staff_extent.contains (i->second[d].max_position_
+ - sign (i->second[d].max_position_)));
+
+ for (LEFT_and_RIGHT (which))
+ {
+ Ledger_request &lr = ((which == LEFT) ? * last : *i).second[d];
+
+ Real limit = (center + (both ? which * gap / 2 : 0));
+ lr.max_ledger_extent_.at (-which)
+ = which * max (which * lr.max_ledger_extent_[-which],
+ which * limit);
+ }
+ }
+ }
+ }
+
+ // Iterate through ledger requests and the data they have about each
+ // note head to generate the final extents for all ledger lines.
+ // Note heads that are different widths produce different ledger
+ // extents and these are merged so the widest extent prevails
+ // (the union of the intervals) for each ledger line.
+ for (Ledger_requests::iterator i (reqs.begin ());
+ i != reqs.end (); i++)
+ {
+ for (DOWN_and_UP (d))
+ {
+ Ledger_request &lr = i->second[d];
+ for (vsize h = 0; h < lr.heads_.size (); h++)
+ {
+ vector<Real> &ledger_posns = lr.heads_[h].ledger_positions_;
+ Interval &ledger_size = lr.heads_[h].ledger_extent_;
+ Interval &head_size = lr.heads_[h].head_extent_;
+ Interval &acc_extent = lr.heads_[h].accidental_extent_;
+
+ // Limit ledger extents to a maximum to preserve space
+ // between ledgers when note heads get close.
+ if (!lr.max_ledger_extent_.is_empty ())
+ ledger_size.intersect (lr.max_ledger_extent_);
+
+ // Iterate through the ledgers for a given note head.
+ for (vsize l = 0; l < ledger_posns.size (); l++)
+ {
+ Real lpos = ledger_posns[l];
+ Interval x_extent = ledger_size;
+
+ // Notes with accidental signs get shorter ledgers.
+ // (Only happens for the furthest note in the column.)
+ if (l == 0 && !acc_extent.is_empty ())
+ {
+ Real dist
+ = linear_combination (Drul_array<Real> (acc_extent[RIGHT],
+ head_size[LEFT]),
+ 0.0);
+
+ Real left_shorten = max (-ledger_size[LEFT] + dist, 0.0);
+ x_extent[LEFT] += left_shorten;
+ /*
+ TODO: shorten 2 ledger lines for the case
+ natural + downstem.
+ */
+ }
+ if (lr.ledger_extents_.find (lpos) == lr.ledger_extents_.end ())
+ lr.ledger_extents_[lpos] = x_extent;
+ else
+ lr.ledger_extents_[lpos].unite (x_extent);
+ }
+ }
+ }