package com.xenoage.zong.io;
import com.xenoage.utils.exceptions.InvalidFormatException;
import com.xenoage.utils.math.geom.Point2f;
import com.xenoage.utils.math.geom.Size2f;
import com.xenoage.zong.core.Score;
import com.xenoage.zong.core.format.LayoutFormat;
import com.xenoage.zong.core.format.PageFormat;
import com.xenoage.zong.documents.ScoreDoc;
import com.xenoage.zong.layout.Layout;
import com.xenoage.zong.layout.LayoutDefaults;
import com.xenoage.zong.layout.Page;
import com.xenoage.zong.layout.frames.ScoreFrame;
import com.xenoage.zong.layout.frames.ScoreFrameChain;
import com.xenoage.zong.musiclayout.ScoreLayout;
import com.xenoage.zong.musiclayout.layouter.ScoreLayoutArea;
import com.xenoage.zong.musiclayout.layouter.ScoreLayouter;
import com.xenoage.zong.musiclayout.layouter.Target;
import lombok.Getter;
import lombok.Setter;
import java.io.IOException;
import static com.xenoage.zong.core.format.LayoutFormat.defaultLayoutFormat;
/**
* Creates a {@link ScoreDoc} from a {@link Score}.
*
* @author Andreas Wenger
*/
public class ScoreDocFactory {
/** If true, an error layout is used when there a problems during layouting the score.
Otherwise, an exception is thrown.
TODO: maybe provide this value over dependency injection DEPENDENCYINJECTION */
@Getter @Setter private static boolean isErrorLayoutEnabled = true;
/**
* Creates a {@link ScoreDoc} instance from the given score.
* TIDY: move elsewhere, e.g. in a ScoreDocFactory class
*/
public ScoreDoc read(Score score)
throws InvalidFormatException, IOException {
//page format
LayoutFormat layoutFormat = defaultLayoutFormat;
Object oLayoutFormat = score.getMetaData().get("layoutformat");
if (oLayoutFormat instanceof LayoutFormat) {
layoutFormat = (LayoutFormat) oLayoutFormat;
}
LayoutDefaults layoutDefaults = new LayoutDefaults(layoutFormat);
//create the document
ScoreDoc ret = new ScoreDoc(score, layoutDefaults);
Layout layout = ret.getLayout();
//layout basics
PageFormat pageFormat = layoutFormat.getPageFormat(0);
Size2f frameSize = new Size2f(pageFormat.getUseableWidth(), pageFormat.getUseableHeight());
Point2f framePos = new Point2f(pageFormat.getMargins().getLeft() + frameSize.width / 2,
pageFormat.getMargins().getTop() + frameSize.height / 2);
//layout the score to find out the needed space
Target target = Target.completeLayoutTarget(new ScoreLayoutArea(frameSize));
ScoreLayouter layouter = new ScoreLayouter(ret, target);
ScoreLayout scoreLayout = isErrorLayoutEnabled ?
layouter.createScoreLayout() : layouter.createLayoutWithExceptions();
//create and fill at least one page
if (scoreLayout.frames.size() > 0) {
//normal layout: one frame per page
ScoreFrameChain chain = null;
for (int i = 0; i < scoreLayout.frames.size(); i++) {
Page page = new Page(pageFormat);
layout.addPage(page);
ScoreFrame frame = new ScoreFrame();
frame.setPosition(framePos);
frame.setSize(frameSize);
//TEST frame = frame.withHFill(NoHorizontalSystemFillingStrategy.getInstance());
page.addFrame(frame);
if (chain == null) {
chain = new ScoreFrameChain(score);
chain.setScoreLayout(scoreLayout);
}
chain.add(frame);
}
}
else {
//no frames: create a single empty page
Page page = new Page(pageFormat);
layout.addPage(page);
}
return ret;
}
}