package com.xenoage.zong.musiclayout.stamper; import static com.xenoage.utils.collections.CollectionUtils.alist; import static com.xenoage.utils.kernel.Range.range; import static com.xenoage.zong.musiclayout.stamper.ChordStamper.chordStamper; import static com.xenoage.zong.musiclayout.stamper.ElementStamper.elementStamper; import java.util.List; import java.util.Map; import com.xenoage.zong.core.music.MusicElement; import com.xenoage.zong.core.music.VoiceElement; import com.xenoage.zong.core.music.beam.Beam; import com.xenoage.zong.core.music.chord.Chord; import com.xenoage.zong.core.text.FormattedTextStyle; import com.xenoage.zong.musiclayout.layouter.cache.OpenLyricsCache; import com.xenoage.zong.musiclayout.layouter.cache.OpenSlursCache; import com.xenoage.zong.musiclayout.layouter.cache.OpenTupletsCache; import com.xenoage.zong.musiclayout.layouter.scoreframelayout.util.LastLyrics; import com.xenoage.zong.musiclayout.layouter.scoreframelayout.util.StaffStampings; import com.xenoage.zong.musiclayout.notation.ChordNotation; import com.xenoage.zong.musiclayout.notation.Notation; import com.xenoage.zong.musiclayout.spacing.BeamSpacing; import com.xenoage.zong.musiclayout.spacing.ElementSpacing; import com.xenoage.zong.musiclayout.spacing.MeasureSpacing; import com.xenoage.zong.musiclayout.spacing.RestSpacing; import com.xenoage.zong.musiclayout.spacing.VoiceSpacing; import com.xenoage.zong.musiclayout.stampings.Stamping; /** * Creates the {@link Stamping}s for {@link VoiceElement}s. * * @author Andreas Wenger */ public class VoiceStamper { public static final VoiceStamper voiceStamper = new VoiceStamper(); public List<Stamping> stampVoices(MeasureSpacing measure, float voicesXMm, StaffStampings staffStampings, StamperContext context, //TODO: FormattedTextStyle defaultLyricStyle, Map<Beam, BeamSpacing> beams, OpenSlursCache openCurvedLinesCache, OpenLyricsCache openLyricsCache, LastLyrics lastLyrics, OpenTupletsCache openTupletsCache) { List<Stamping> ret = alist(); context.layouter.saveMp(); //iterate over the voices for (int iVoice : range(measure.voices)) { context.layouter.mp = context.layouter.mp.withVoice(iVoice); VoiceSpacing voice = measure.voices.get(iVoice); //don't stamp leading rests in non-first voices boolean stampLeadingRests = (iVoice == 0); //create voice stampings ret.addAll(stampVoice(voice, voicesXMm, staffStampings, stampLeadingRests, context, defaultLyricStyle, beams, openCurvedLinesCache, openLyricsCache, lastLyrics, openTupletsCache)); } context.layouter.restoreMp(); return ret; } public List<Stamping> stampVoice(VoiceSpacing voice, float voiceXMm, StaffStampings staffStampings, boolean stampLeadingRests, StamperContext context, //TODO: FormattedTextStyle defaultLyricStyle, Map<Beam, BeamSpacing> beams, OpenSlursCache openCurvedLinesCache, OpenLyricsCache openLyricsCache, LastLyrics lastLyrics, OpenTupletsCache openTupletsCache) { List<Stamping> ret = alist(); //create the voice elements boolean onlyRestsSoFar = true; for (ElementSpacing spacingElement : voice.elements) { MusicElement element = spacingElement.getElement(); if (element != null /* TODO && (stampRests || !(element instanceof Rest)) */) { Notation notation = context.getNotation(element); float xMm = voiceXMm + spacingElement.xIs * voice.interlineSpace; if (element instanceof Chord) { //chord onlyRestsSoFar = false; Chord chord = (Chord) element; BeamSpacing beam = beams.get(chord.getBeam()); ret.addAll(chordStamper.stampAll( (ChordNotation) spacingElement.getNotation(), xMm, beam, staffStampings, context, defaultLyricStyle, openCurvedLinesCache, openLyricsCache, lastLyrics, openTupletsCache)); } else if (spacingElement instanceof RestSpacing) { //rest if (false == onlyRestsSoFar || stampLeadingRests) { //not a leading rest, or a leading rest which should be stamped ret.add(elementStamper.createRestStamping( (RestSpacing) spacingElement, xMm, context)); } } else { throw new IllegalArgumentException("Notation not supported: " + notation); } } } return ret; } }