package com.xenoage.zong.musiclayout.notator.chord.stem;
import com.xenoage.utils.annotations.MaybeNull;
import com.xenoage.zong.core.music.StaffLines;
import com.xenoage.zong.core.music.chord.Stem;
import com.xenoage.zong.core.music.chord.StemDirection;
import com.xenoage.zong.musiclayout.notation.chord.ChordLps;
import com.xenoage.zong.musiclayout.notation.chord.StemNotation;
import static com.xenoage.zong.core.music.chord.StemDirection.*;
import static com.xenoage.zong.musiclayout.SLP.slp;
import static com.xenoage.zong.musiclayout.notator.chord.stem.StemDrawer.stemDrawer;
/**
* Computes the {@link StemNotation} of a chord stem.
*
* If there is a fixed stem length, it is used, otherwise a good value is computed.
* Each chord is handled separately. Beams are not handled by this class, i.e. the
* length of the stem is computed as if there was no beam.
*
* @author Andreas Wenger
*/
public class StemNotator {
public static final StemNotator stemNotator = new StemNotator();
/**
* Computes the vertical position of the stem of the given chord layout.
* @param stem the stem of the chord (direction is ignored)
* @param notesLp the positions of the notes of of the chord
* @param stemDir the direction of the stem
* @param staffLines the number of lines in this staff
* @param scaling scaling of the whole chord (e.g. smaller than 1 for a grace chord).
* ignored if the stem has a given fixed length
* @return the vertical position of the stem, or null if the chord has no stem.
*/
@MaybeNull public StemNotation compute(Stem stem, ChordLps notesLp, StemDirection stemDir,
int staffIndex, StaffLines staffLines, float scaling) {
float startLp = 0, innerLp = 0, endLp;
//use a stem?
if (stemDir == None)
return null;
//compute start position
if (stemDir == Down) {
startLp = notesLp.getTop();
innerLp = notesLp.getBottom();
}
else if (stemDir == Up) {
startLp = notesLp.getBottom();
innerLp = notesLp.getTop();
}
//compute end position
float stemLengthIs;
if (stem.getLengthIs() != null) {
//used fixed length
stemLengthIs = stem.getLengthIs();
}
else {
//compute length
stemLengthIs = stemDrawer.getPreferredStemLengthIs(notesLp, stemDir, staffLines);
}
endLp = innerLp + stemDir.getSign() * stemLengthIs * 2;
return new StemNotation(slp(staffIndex, startLp), slp(staffIndex, endLp));
}
}