package com.xenoage.zong.musiclayout.notator.chord.accidentals; import static com.xenoage.utils.kernel.Range.range; import java.util.List; import com.xenoage.zong.core.music.MusicContext; import com.xenoage.zong.core.music.Pitch; import com.xenoage.zong.core.music.chord.Accidental; import com.xenoage.zong.musiclayout.notation.chord.AccidentalDisplacement; import com.xenoage.zong.musiclayout.notation.chord.AccidentalsNotation; import com.xenoage.zong.musiclayout.notation.chord.NoteDisplacement; import com.xenoage.zong.musiclayout.settings.ChordWidths; /** * Strategy for displacing accidentals. * Thread-safe. * * TODO (ZONG-89): Use free space in accidentals to bring them closer together. * * @author Andreas Wenger */ public abstract class Strategy { static class Params { //all accidentals, ascending LP Accidental[] accs; //all notes with accidentals, ascending LP NoteDisplacement[] accsNote; //widths of musical symbols ChordWidths chordWidths; } public AccidentalsNotation computeAccidentalsDisplacement(List<Pitch> pitches, NoteDisplacement[] notes, int accsCount, ChordWidths chordWidths, MusicContext mc) { Params params = getParams(pitches, notes, accsCount, chordWidths, mc); return compute(params); } abstract AccidentalsNotation compute(Params params); static Params getParams(List<Pitch> pitches, NoteDisplacement[] notes, int accsCount, ChordWidths chordWidths, MusicContext mc) { Params params = new Params(); params.accs = new Accidental[accsCount]; params.accsNote = new NoteDisplacement[params.accs.length]; int lastIndex = -1; for (int i : range(params.accs)) { int index = getAccNoteIndex(pitches, lastIndex + 1, mc); params.accs[i] = mc.getAccidental(pitches.get(index)); params.accsNote[i] = notes[index]; lastIndex = index; } params.chordWidths = chordWidths; return params; } static int getAccNoteIndex(List<Pitch> pitches, int startIndex, MusicContext mc) { for (int i : range(startIndex, pitches.size() - 1)) if (mc.getAccidental(pitches.get(i)) != null) return i; throw new IllegalStateException(); } static AccidentalsNotation create(Params params, float widthIs, float... xIs) { AccidentalDisplacement[] a = new AccidentalDisplacement[xIs.length]; for (int i : range(a)) a[i] = new AccidentalDisplacement(params.accsNote[i].lp, xIs[i], params.accs[i]); return new AccidentalsNotation(a, widthIs); } }