package com.xenoage.zong.musiclayout.spacer.measure; import com.xenoage.utils.math.Delta; import com.xenoage.utils.math.Fraction; import com.xenoage.zong.core.music.clef.Clef; import com.xenoage.zong.core.music.clef.ClefType; import com.xenoage.zong.core.music.rest.Rest; import com.xenoage.zong.core.music.util.BeatEList; import com.xenoage.zong.musiclayout.notation.ClefNotation; import com.xenoage.zong.musiclayout.notation.Notations; import com.xenoage.zong.musiclayout.notation.RestNotation; import com.xenoage.zong.musiclayout.settings.LayoutSettings; import com.xenoage.zong.musiclayout.spacing.ElementSpacing; import com.xenoage.zong.musiclayout.spacing.ElementWidth; import com.xenoage.zong.musiclayout.spacing.SimpleSpacing; import com.xenoage.zong.musiclayout.spacing.VoiceSpacing; import org.junit.Test; import java.util.List; import static com.xenoage.utils.collections.CList.ilist; import static com.xenoage.utils.collections.CollectionUtils.alist; import static com.xenoage.utils.kernel.Range.range; import static com.xenoage.utils.math.Delta.df; import static com.xenoage.utils.math.Fraction.fr; import static com.xenoage.zong.core.music.util.BeatE.beatE; import static com.xenoage.zong.core.music.util.BeatEList.beatEList; import static com.xenoage.zong.musiclayout.settings.LayoutSettings.defaultLayoutSettings; import static com.xenoage.zong.musiclayout.spacer.measure.MeasureElementsSpacer.measureElementsSpacer; import static org.junit.Assert.*; /** * Tests for the {@link MeasureElementsSpacer}. * * In these tests, we assume a width for the padding of * 1 IS and for the clef of 6 IS. * * @author Andreas Wenger */ public class MeasureElementsSpacerTest { private MeasureElementsSpacer testee = measureElementsSpacer; private float paddingWidth = 1; private float clefWidth = 6; private LayoutSettings ls = defaultLayoutSettings; /** * If there is enough space left for the measure elements, * the voice spacings do not have to be changed. * To understand the following sketch, have a look at the comments * in {@link MeasureElementsSpacer}. * <pre> * enough space: * beat: 0 2 4 6 8 * offset: 3 5 7 9 13 17 21 * . . . . . . . . . . * clef: *[clef]* (on beat 6) * voice 1: o 2 * voice 2: 1 o * </pre> */ @Test public void testEnoughExistingSpace() { Rest[] ve = ve(); List<VoiceSpacing> originalVs = alist( new VoiceSpacing(null, 1, alist(spacing(ve[0], fr(1, 2), 4), spacing(ve[1], fr(6), 15))), new VoiceSpacing(null, 1, alist(spacing(ve[2], fr(1), 5), spacing(ve[3], fr(17, 2), 20)))); List<VoiceSpacing> vs = alist(originalVs); Clef innerClef = new Clef(ClefType.clefTreble); BeatEList<Clef> innerClefs = beatEList(); innerClefs.add(beatE(innerClef, fr(6))); List<ElementSpacing> res = testee.compute( innerClefs, beatEList(), null, false, vs, 0, notations(ve, innerClef), ls); //clef must be at offset 15 - padding - clefwidth/2 ElementSpacing[] mes = res.toArray(new ElementSpacing[0]); assertEquals(1, mes.length); assertEquals(fr(6), mes[0].beat); assertEquals(15 - paddingWidth - clefWidth / 2, mes[0].xIs, Delta.DELTA_FLOAT); //voice spacings must be unchanged assertEquals(originalVs, vs); } /** * If there is not enough space left for the measure elements, * the voice spacings have to be moved to create enough space. * To understand the following sketch, have a look at the comments * in {@link MeasureElementsSpacer}. * <pre> * enough space: * beat: 0 2 4 6 8 * offset: 3 5 7 9 13 17 21 * . . . . . . . . . . * clef: *[clef]* (on beat 4) * voice 1: o 2 * voice 2: 1 o * </pre> * Between VE1 and VE2, there are 6 spaces. * Assuming a padding width of 1 and a clef width of 6, * the clef can be moved two spaces to the left, but this is not * enough. All elements at or after beat 3 have to be moved 2 spaces * to the right. */ @Test public void testNeedAdditionalSpace() { Rest[] ve = ve(); List<VoiceSpacing> vs = alist( new VoiceSpacing(null, 1, alist(spacing(ve[0], fr(1, 2), 4), spacing(ve[1], fr(4), 11))), new VoiceSpacing(null, 1, alist(spacing(ve[2], fr(1), 5), spacing(ve[3], fr(13, 2), 16)))); Clef innerClef = new Clef(ClefType.clefTreble); BeatEList<Clef> innerClefs = beatEList(); innerClefs.add(beatE(innerClef, fr(4))); List<ElementSpacing> mes = testee.compute( innerClefs, beatEList(), null, false, vs, 0, notations(ve, innerClef), ls); //voice spacings assertEquals(2, vs.size()); assertEqualsSpacings(ilist(spacing(ve[0], fr(1, 2), 4), spacing(ve[1], fr(4), 13)), vs.get(0).elements); assertEqualsSpacings(ilist(spacing(ve[2], fr(1), 5), spacing(ve[3], fr(13, 2), 18)), vs.get(1).elements); //clef must be at offset 13 - padding - clefwidth/2 ElementSpacing[] se = mes.toArray(new ElementSpacing[0]); assertEquals(1, se.length); assertEquals(fr(4), se[0].beat); assertEquals(13 - paddingWidth - clefWidth / 2, se[0].xIs, Delta.DELTA_FLOAT); } private void assertEqualsSpacings(List<ElementSpacing> expected, List<ElementSpacing> actual) { assertEquals(expected.size(), actual.size()); for (int i : range(expected)) { assertEquals(expected.get(i).getElement(), expected.get(i).getElement()); assertEquals(expected.get(i).beat, expected.get(i).beat); assertEquals(expected.get(i).xIs, expected.get(i).xIs, df); } } private Rest[] ve() { return new Rest[] { new Rest(fr(1)), new Rest(fr(1)), new Rest(fr(1)), new Rest(fr(1)) }; } private ElementSpacing spacing(Rest rest, Fraction beat, float offset) { return new SimpleSpacing(new RestNotation(rest, new ElementWidth(0), null), beat, offset); } private Notations notations(Rest[] rests, Clef clef) { Notations ret = new Notations(); ret.add(new ClefNotation(clef, new ElementWidth(clefWidth), 0, 1)); return ret; } }