- Item *h = dynamic_cast<Item *> (heads[i]);
-
- int pos = Staff_symbol_referencer::get_rounded_position (h);
- if (!staff_extent.contains (pos - sign (pos)))
- {
- Interval head_size = h->extent (common[X_AXIS], X_AXIS);
- Interval ledger_size = head_size;
- ledger_size.widen (ledger_size.length () * length_fraction);
-
- Interval max_size = reqs[h->get_column ()->get_rank ()]
- [Direction (sign (pos))].ledger_extent_;
-
- ledger_size.intersect (max_size);
- Real left_shorten = 0.0;
- if (Grob *g = unsmob_grob (h->get_object ("accidental-grob")))
- {
- Interval accidental_size = g->extent (common[X_AXIS], X_AXIS);
- Real d
- = linear_combination (Drul_array<Real> (accidental_size[RIGHT],
- head_size[LEFT]),
- 0.0);
-
- left_shorten = max (-ledger_size[LEFT] + d, 0.0);
-
- /*
- TODO: shorten 2 ledger lines for the case natural +
- downstem.
- */
- }
-
- ledgers.add_stencil (brew_ledger_lines (staff, pos, staff_extent,
- halfspace,
- ledgerlinethickness,
- ledger_size,
- left_shorten));
- }
+ 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.
+ */
+ }
+ // When the extents of two ledgers at the same
+ // vertical position overlap horizontally, we merge
+ // them together to produce a single stencil. In rare
+ // cases they do not overlap and we do not merge them.
+
+ if (lr.ledger_extents_.find (lpos) == lr.ledger_extents_.end ())
+ // Found nothing for this lpos.
+ lr.ledger_extents_[lpos].push_back(x_extent);
+ else
+ {
+ vector<Interval> &extents = lr.ledger_extents_.find (lpos)->second;
+ for (vsize e = 0; e < extents.size (); e++)
+ {
+ if (intersection (extents[e], x_extent).is_empty ())
+ extents.push_back (x_extent);
+ else
+ extents[e].unite (x_extent);
+ }
+ }
+ }
+ }
+ }