package com.xenoage.zong.musiclayout.spacer;
import static com.xenoage.utils.collections.CollectionUtils.alist;
import static com.xenoage.zong.core.position.MP.atMeasure;
import static com.xenoage.zong.musiclayout.spacer.frame.FrameSpacer.frameSpacer;
import java.util.ArrayList;
import java.util.List;
import com.xenoage.utils.math.geom.Size2f;
import com.xenoage.zong.musiclayout.layouter.Context;
import com.xenoage.zong.musiclayout.layouter.Target;
import com.xenoage.zong.musiclayout.notation.Notations;
import com.xenoage.zong.musiclayout.spacing.ColumnSpacing;
import com.xenoage.zong.musiclayout.spacing.FrameSpacing;
import com.xenoage.zong.musiclayout.spacing.FramesSpacing;
/**
* Breaks the given optimal measure column spacings into systems and frames.
*
* @author Andreas Wenger
*/
public class FramesSpacer {
public static final FramesSpacer framesSpacer = new FramesSpacer();
public FramesSpacing compute(List<ColumnSpacing> columns,
Target target, Context context, Notations notations) {
context.saveMp();
ArrayList<FrameSpacing> frames = alist();
int measuresCount = context.score.getMeasuresCount();
int iMeasure = 0;
int iSystem = 0;
int iFrame = 0;
boolean additionalFrameIteration;
while (true) {
additionalFrameIteration = false;
//find score frame
Size2f frameSize;
if (iFrame < target.areas.size()) {
//there is another existing score frame
frameSize = target.getArea(iFrame).sizeMm;
}
else {
//there is no another existing score frame
if (false == target.isCompleteLayout) {
//we are not interested in the stuff after the last score frame. exit.
break;
}
else if (iMeasure >= measuresCount) {
//all measures layouted. exit.
break;
}
else {
//still material to layout and additional frames requested. create one.
frameSize = target.additionalArea.sizeMm;
additionalFrameIteration = true;
}
}
//some material left to layout?
if (iMeasure < measuresCount) {
//more measures to layout
context.mp = atMeasure(iMeasure);
FrameSpacing frame = frameSpacer.compute(context, iSystem, frameSize,
additionalFrameIteration, columns, notations);
if (frame.getSystems().size() > 0) {
//at least one measure in this frame. remember frame
frames.add(frame);
iMeasure = frame.getEndMeasure() + 1;
iSystem += frame.getSystems().size();
}
else {
//no space for a measure in this frame. empty frame. but only, if frame exists.
//do not create endless list of empty additional frames
if (!additionalFrameIteration) {
frames.add(FrameSpacing.empty(frameSize));
}
else {
break;
}
}
}
else {
//no material left. empty frame.
frames.add(FrameSpacing.empty(frameSize));
}
//next frame
iFrame++;
}
context.restoreMp();
return new FramesSpacing(frames);
}
}