Search in sources :

Example 1 with ScoreFormat

use of com.xenoage.zong.core.format.ScoreFormat in project Zong by Xenoage.

the class ScoreDocScoreView method updateScreen.

@Override
public void updateScreen(Size2i screenSizePx, float zoom) {
    this.screenSizePx = screenSizePx;
    this.zoom = zoom;
    // recompute the layout, so that each page fits into the available screen space
    Size2f pageSizeMm = pxToMm(screenSizePx, zoom);
    float marginMm = pxToMm(marginPx, zoom);
    PageFormat pageFormat = new PageFormat(pageSizeMm, new PageMargins(marginMm, marginMm, marginMm, marginMm));
    Size2f frameSizeMm = new Size2f(pageFormat.getUseableWidth(), pageFormat.getUseableHeight());
    // first page needs space for title text
    titleTextHeightPx = screenSizePx.height / 20f;
    float firstFrameOffsetY = pxToMm(titleTextHeightPx, zoom);
    Size2f firstFrameSizeMm = new Size2f(frameSizeMm.width, frameSizeMm.height - firstFrameOffsetY);
    // delete unnecessary layout information, like system distances or system breaks
    Score score = doc.getScore();
    score.setFormat(new ScoreFormat());
    ScoreHeader header = score.getHeader();
    for (int i : range(header.getSystemLayouts())) {
        SystemLayout sl = header.getSystemLayout(i);
        if (sl != null)
            sl.setDistance(SystemLayout.defaultDistance);
    }
    for (int i : range(header.getColumnHeaders())) {
        ColumnHeader ch = header.getColumnHeader(i);
        if (ch.getMeasureBreak() != null)
            ch.setBreak(null);
    }
    // layout the score to find out the needed space
    Context context = new Context(score, App.getSymbolPool(), doc.getLayout().getDefaults().getLayoutSettings());
    Target target = new Target(alist(new ScoreLayoutArea(firstFrameSizeMm)), new ScoreLayoutArea(frameSizeMm), true);
    ScoreLayouter layouter = new ScoreLayouter(context, target);
    ScoreLayout scoreLayout = layouter.createScoreLayout();
    // create and fill at least one page
    Layout layout = new Layout(doc.getLayout().getDefaults());
    ScoreFrameChain chain = null;
    for (int i = 0; i < scoreLayout.frames.size(); i++) {
        Page page = new Page(pageFormat);
        Point2f position;
        Size2f size;
        if (i == 0) {
            // first page
            position = new Point2f(pageSizeMm.width / 2, pageSizeMm.height / 2 + firstFrameOffsetY);
            size = firstFrameSizeMm;
        } else {
            // other pages
            position = new Point2f(pageSizeMm.width / 2, pageSizeMm.height / 2);
            size = frameSizeMm;
        }
        ScoreFrame frame = new ScoreFrame();
        frame.setPosition(position);
        frame.setSize(size);
        page.addFrame(frame);
        layout.addPage(page);
        if (chain == null) {
            chain = new ScoreFrameChain(score);
            chain.setScoreLayout(scoreLayout);
        }
        chain.add(frame);
    }
    this.layout = layout;
}
Also used : Context(com.xenoage.zong.musiclayout.layouter.Context) ScoreFrame(com.xenoage.zong.layout.frames.ScoreFrame) ScoreLayouter(com.xenoage.zong.musiclayout.layouter.ScoreLayouter) ScoreLayout(com.xenoage.zong.musiclayout.ScoreLayout) Page(com.xenoage.zong.layout.Page) Paint(android.graphics.Paint) ScoreFormat(com.xenoage.zong.core.format.ScoreFormat) PageMargins(com.xenoage.zong.core.format.PageMargins) PageFormat(com.xenoage.zong.core.format.PageFormat) Score(com.xenoage.zong.core.Score) ScoreHeader(com.xenoage.zong.core.header.ScoreHeader) ColumnHeader(com.xenoage.zong.core.header.ColumnHeader) Target(com.xenoage.zong.musiclayout.layouter.Target) Point2f(com.xenoage.utils.math.geom.Point2f) ScoreLayout(com.xenoage.zong.musiclayout.ScoreLayout) SystemLayout(com.xenoage.zong.core.format.SystemLayout) Layout(com.xenoage.zong.layout.Layout) SystemLayout(com.xenoage.zong.core.format.SystemLayout) ScoreFrameChain(com.xenoage.zong.layout.frames.ScoreFrameChain) Size2f(com.xenoage.utils.math.geom.Size2f) ScoreLayoutArea(com.xenoage.zong.musiclayout.layouter.ScoreLayoutArea)

Example 2 with ScoreFormat

use of com.xenoage.zong.core.format.ScoreFormat in project Zong by Xenoage.

the class MusicXmlScoreFileInput method read.

/**
 * Builds a {@link Score} entity from a {@link MxlScorePartwise} document.
 * @param doc            the provided score-partwise document
 * @param errorHandling  how to deal with errors
 */
public Score read(MxlScorePartwise mxlScore, Level errorHandling) throws InvalidFormatException {
    try {
        // create new score
        Score score = new Score();
        // read information about the score
        ScoreInfo scoreInfo = new ScoreInfoReader(mxlScore.getScoreHeader()).read();
        score.setInfo(scoreInfo);
        // read score format
        MxlScoreHeader mxlScoreHeader = mxlScore.getScoreHeader();
        MxlDefaults mxlDefaults = mxlScoreHeader.getDefaults();
        ScoreFormat scoreFormat = new ScoreFormatReader(mxlDefaults).read();
        score.setFormat(scoreFormat);
        // read layout format
        MxlLayout mxlLayout = (mxlDefaults != null ? mxlDefaults.getLayout() : null);
        LayoutFormat layoutFormat = new LayoutFormatReader(mxlLayout, scoreFormat.getInterlineSpace() / 10).read();
        // TIDY
        score.setMetaData("layoutformat", layoutFormat);
        // create the list of staves
        ErrorHandling mxlErrorHandling = new ErrorHandling(errorHandling);
        StavesListReader stavesListReader = new StavesListReader(mxlScore, mxlErrorHandling);
        StavesList stavesList = stavesListReader.read();
        stavesList.setScore(score);
        score.setStavesList(stavesList);
        // read the musical contents
        new ScoreReader(mxlScore).readToScore(score, mxlErrorHandling);
        // remember the XML document for further application-dependend processing
        // TIDY
        score.setMetaData("mxldoc", mxlScore);
        // when errors were collected, log them and save them as metadata
        if (mxlErrorHandling.getErrorMessages().size() > 0) {
            INSTANCE.log(Companion.warning("The file could be loaded, but the following error(s) were reported: " + mxlErrorHandling.getErrorMessages()));
            score.setMetaData("mxlerrors", mxlErrorHandling.getErrorMessages());
        }
        return score;
    } catch (RuntimeException ex) {
        // catch runtime exceptions and rethrow them in the expected type
        throw new InvalidFormatException(ex);
    }
}
Also used : ErrorHandling(com.xenoage.zong.io.musicxml.in.util.ErrorHandling) LayoutFormatReader(com.xenoage.zong.io.musicxml.in.readers.LayoutFormatReader) MxlDefaults(com.xenoage.zong.musicxml.types.MxlDefaults) MxlLayout(com.xenoage.zong.musicxml.types.groups.MxlLayout) LayoutFormat(com.xenoage.zong.core.format.LayoutFormat) ScoreReader(com.xenoage.zong.io.musicxml.in.readers.ScoreReader) InvalidFormatException(com.xenoage.utils.exceptions.InvalidFormatException) ScoreFormat(com.xenoage.zong.core.format.ScoreFormat) Score(com.xenoage.zong.core.Score) ScoreInfo(com.xenoage.zong.core.info.ScoreInfo) StavesList(com.xenoage.zong.core.music.StavesList) ScoreFormatReader(com.xenoage.zong.io.musicxml.in.readers.ScoreFormatReader) ScoreInfoReader(com.xenoage.zong.io.musicxml.in.readers.ScoreInfoReader) MxlScoreHeader(com.xenoage.zong.musicxml.types.groups.MxlScoreHeader) StavesListReader(com.xenoage.zong.io.musicxml.in.readers.StavesListReader)

Example 3 with ScoreFormat

use of com.xenoage.zong.core.format.ScoreFormat in project Zong by Xenoage.

the class StavesSpacer method compute.

public StavesSpacing compute(Score score, int systemIndex) {
    // compute staff distances
    ScoreFormat scoreFormat = score.getFormat();
    ScoreHeader scoreHeader = score.getHeader();
    float[] distancesMm = new float[score.getStavesCount() - 1];
    for (int iStaff : range(1, distancesMm.length)) {
        StaffLayout staffLayout = scoreHeader.getStaffLayout(systemIndex, iStaff);
        float staffDistanceMm = 0;
        if (staffLayout != null) {
            // use custom staff distance
            staffDistanceMm = staffLayout.getDistance();
        } else {
            // use default staff distance
            staffDistanceMm = scoreFormat.getStaffLayoutNotNull(iStaff).getDistance();
        }
        distancesMm[iStaff - 1] = staffDistanceMm;
    }
    // create spacing
    StavesSpacing stavesSpacing = new StavesSpacing(score.getStavesList().getStaves(), distancesMm, scoreFormat.getInterlineSpace());
    return stavesSpacing;
}
Also used : ScoreFormat(com.xenoage.zong.core.format.ScoreFormat) ScoreHeader(com.xenoage.zong.core.header.ScoreHeader) StavesSpacing(com.xenoage.zong.musiclayout.spacing.StavesSpacing) StaffLayout(com.xenoage.zong.core.format.StaffLayout)

Example 4 with ScoreFormat

use of com.xenoage.zong.core.format.ScoreFormat in project Zong by Xenoage.

the class SystemSpacer method compute.

/**
 * Arranges an optimum number of measures columns in a system, beginning at the given measure,
 * if possible.
 * @param context        the context of the layouter, with the {@link MP} set to the start measure
 * @param usableSizeMm   the usable size within the score frame in mm
 * @param offsetYMm      the vertical offset of the system in mm
 * @param systemIndex    the global system index (over all frames)
 * @param isFirst        true, iff this system is the first one in a score frame
 * @param isAdditional   true, iff this system is created for an additional frame, which is created
 *                       for a complete score layout, but is not part of the defined layout
 * @param measureColumnSpacings  a list of all measure column spacings without leading spacings
 * @param notations      the notations of the elements, needed when a column has to be recomputed
 *                       because of a leading spacing
 */
public Optional<SystemSpacing> compute(Context context, Size2f usableSizeMm, float offsetYMm, int systemIndex, boolean isFirst, boolean isAdditional, List<ColumnSpacing> measureColumnSpacings, Notations notations) {
    int startMeasure = context.mp.measure;
    // test if there is enough height for the system
    Score score = context.score;
    ScoreFormat scoreFormat = score.getFormat();
    ScoreHeader scoreHeader = score.getHeader();
    // compute spacing of staves
    StavesSpacing stavesSpacing = stavesSpacer.compute(score, systemIndex);
    // enough space?
    if (offsetYMm + stavesSpacing.getTotalHeightMm() > usableSizeMm.height) {
        // when the system is the first one in an additional frame, we force it into the frame
        if (false == (isFirst && isAdditional))
            // not enough space
            return absent();
    }
    // compute the usable width for the system
    float systemLeftMarginMm = getLeftMarginMm(systemIndex, scoreFormat, scoreHeader);
    float systemRightMarginMm = getRightMarginMm(systemIndex, scoreFormat, scoreHeader);
    float usableWidthMm = usableSizeMm.width - systemLeftMarginMm - systemRightMarginMm;
    // append system measure-by-measure, until there is no space any more
    // or until there are no measures left
    int measuresCount = score.getMeasuresCount();
    List<ColumnSpacing> system = alist();
    float usedWidthMm = 0;
    int iMeasure;
    while (startMeasure + system.size() < measuresCount) {
        iMeasure = startMeasure + system.size();
        // decide if to add a leading spacing to the current measure or not
        boolean firstMeasure = system.size() == 0;
        ColumnSpacing column;
        if (firstMeasure) {
            // first measure within this system: add leading elements (clef, time sig.)
            column = columnSpacer.compute(context, true, /* leading! */
            notations);
        } else {
            // otherwise: use the precomputed spacing (without leading spacing)
            column = measureColumnSpacings.get(iMeasure);
        }
        // this system is created for a complete score layout
        if (false == canAppend(column, iMeasure, usableWidthMm, usedWidthMm, scoreHeader, firstMeasure)) {
            if (system.size() == 0 && isAdditional) {
                // force the single measure in this system
                usedWidthMm += column.getWidthMm();
                system.add(column);
            } else {
                // no more space for another measure
                break;
            }
        } else {
            usedWidthMm += column.getWidthMm();
            system.add(column);
        }
    }
    // we are finished
    if (system.size() == 0) {
        // not enough space for the system on this area
        return absent();
    } else {
        SystemSpacing ret = new SystemSpacing(system, systemLeftMarginMm, systemRightMarginMm, usedWidthMm, stavesSpacing, offsetYMm);
        return of(ret);
    }
}
Also used : ScoreFormat(com.xenoage.zong.core.format.ScoreFormat) Score(com.xenoage.zong.core.Score) ScoreHeader(com.xenoage.zong.core.header.ScoreHeader) StavesSpacing(com.xenoage.zong.musiclayout.spacing.StavesSpacing) ColumnSpacing(com.xenoage.zong.musiclayout.spacing.ColumnSpacing) SystemSpacing(com.xenoage.zong.musiclayout.spacing.SystemSpacing)

Example 5 with ScoreFormat

use of com.xenoage.zong.core.format.ScoreFormat in project Zong by Xenoage.

the class FrameSpacer method compute.

/**
 * Arranges an optimum number of systems in a frame, beginning at the given measure,
 * if possible.
 * @param context         the context of the layouter, with the {@link MP} set to the start measure
 * @param startSystem     the index of the system where to start
 * @param usableSizeMm    the usable size within the score frame in mm
 * @param isAdditional    true, when this frame is created for a complete score layout,
 *                         but is not part of the defined layout
 * @param columnSpacings  a list of all measure column spacings without leading spacings
 * @param notations       the notations of the elements, needed when a column has to be recomputed
 *                        because of a leading spacing
 */
public FrameSpacing compute(Context context, int startSystem, Size2f usableSizeMm, boolean isAdditional, List<ColumnSpacing> columnSpacings, Notations notations) {
    context.saveMp();
    int startMeasure = context.mp.measure;
    Score score = context.score;
    ScoreFormat scoreFormat = score.getFormat();
    ScoreHeader scoreHeader = score.getHeader();
    int measuresCount = score.getMeasuresCount();
    int measureIndex = startMeasure;
    int systemIndex = startSystem;
    // top margin
    float offsetY = getTopSystemDistance(systemIndex, scoreFormat, scoreHeader);
    // append systems to the frame
    List<SystemSpacing> systems = alist();
    while (measureIndex < measuresCount) {
        // try to create system on this frame
        context.mp = atMeasure(measureIndex);
        boolean isFirst = (systems.size() == 0);
        SystemSpacing system = systemSpacer.compute(context, usableSizeMm, offsetY, systemIndex, isFirst, isAdditional, columnSpacings, notations).orNull();
        // was there enough place for this system?
        if (system != null) {
            // yes, there is enough place. add system
            systems.add(system);
            // update offset and start measure index for next system
            // add height of this system
            offsetY += system.getHeightMm();
            // add system distance of the following system
            offsetY += getSystemDistance(systemIndex + 1, scoreFormat, scoreHeader);
            // increase indexes
            systemIndex++;
            measureIndex = system.getEndMeasure() + 1;
        } else {
            break;
        }
    }
    context.restoreMp();
    return new FrameSpacing(systems, usableSizeMm);
}
Also used : ScoreFormat(com.xenoage.zong.core.format.ScoreFormat) Score(com.xenoage.zong.core.Score) ScoreHeader(com.xenoage.zong.core.header.ScoreHeader) FrameSpacing(com.xenoage.zong.musiclayout.spacing.FrameSpacing) SystemSpacing(com.xenoage.zong.musiclayout.spacing.SystemSpacing)

Aggregations

ScoreFormat (com.xenoage.zong.core.format.ScoreFormat)6 Score (com.xenoage.zong.core.Score)4 ScoreHeader (com.xenoage.zong.core.header.ScoreHeader)4 StavesSpacing (com.xenoage.zong.musiclayout.spacing.StavesSpacing)2 SystemSpacing (com.xenoage.zong.musiclayout.spacing.SystemSpacing)2 Paint (android.graphics.Paint)1 NonNull (com.xenoage.utils.annotations.NonNull)1 InvalidFormatException (com.xenoage.utils.exceptions.InvalidFormatException)1 Point2f (com.xenoage.utils.math.geom.Point2f)1 Size2f (com.xenoage.utils.math.geom.Size2f)1 LayoutFormat (com.xenoage.zong.core.format.LayoutFormat)1 PageFormat (com.xenoage.zong.core.format.PageFormat)1 PageMargins (com.xenoage.zong.core.format.PageMargins)1 StaffLayout (com.xenoage.zong.core.format.StaffLayout)1 SystemLayout (com.xenoage.zong.core.format.SystemLayout)1 ColumnHeader (com.xenoage.zong.core.header.ColumnHeader)1 ScoreInfo (com.xenoage.zong.core.info.ScoreInfo)1 StavesList (com.xenoage.zong.core.music.StavesList)1 LayoutFormatReader (com.xenoage.zong.io.musicxml.in.readers.LayoutFormatReader)1 ScoreFormatReader (com.xenoage.zong.io.musicxml.in.readers.ScoreFormatReader)1