getHorizontalOffset method

double getHorizontalOffset(
  1. double staffSpace
)

Get horizontal offset for this voice, in pixels.

Uses horizontalOffset (expressed in staff spaces) when set.

Otherwise the offset follows the stem direction of the voice, per Gould, Behind Bars: when noteheads of opposing voices collide, the stem-down voice is displaced to the right of the stem-up voice so the noteheads stay legible. The offset therefore pairs with getStemDirection:

Voice Stems Offset
1 up none
2 down 0.6 staff spaces
3 up none
4 down 0.6 staff spaces

Limitation: this is a static, per-voice rule. Real engraving only displaces a notehead when the voices actually collide (unison or an interval of a second at the same rhythmic position), and it keeps the column aligned everywhere else. Voices beyond 4 reuse the same odd/even rule; they are rare and usually need manual horizontalOffset.

Implementation

double getHorizontalOffset(double staffSpace) {
  if (horizontalOffset != null) {
    return horizontalOffset! * staffSpace;
  }

  // Stem-up voices (odd) keep the reference column; stem-down voices (even)
  // move right by one notehead width minus the stem, ~0.6 staff spaces.
  return number.isEven ? staffSpace * 0.6 : 0.0;
}