Search in sources :

Example 1 with ColumnHeader

use of com.xenoage.zong.core.header.ColumnHeader 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 ColumnHeader

use of com.xenoage.zong.core.header.ColumnHeader in project Zong by Xenoage.

the class ColumnSpacer method compute.

/**
 * Computes a {@link ColumnSpacing} from a measure column.
 * @param context         the current context, with the current {@link MP} and precomputed
 *                        element {@link Notation}s
 * @param createLeading   true, if a leading spacing has to be created, otherwise false
 * @param notations       the precomputed notations of the measure and voice elements
 */
public ColumnSpacing compute(Context context, boolean createLeading, Notations notations) {
    context.saveMp();
    int measureIndex = context.mp.measure;
    Column column = context.score.getColumn(measureIndex);
    ColumnHeader columnHeader = context.score.getHeader().getColumnHeader(measureIndex);
    // compute the optimal spacings for each voice separately
    List<List<VoiceSpacing>> voiceSpacingsByStaff = alist();
    for (int iStaff : range(column)) {
        List<VoiceSpacing> vss = alist();
        Measure measure = column.get(iStaff);
        for (Voice voice : measure.getVoices()) {
            context.mp = MP.atVoice(iStaff, measureIndex, measure.getVoices().indexOf(voice));
            VoiceSpacing vs = singleVoiceSpacer.compute(context, notations);
            vss.add(vs);
        }
        voiceSpacingsByStaff.add(vss);
    }
    // compute the measure elements (like inner clefs) and accordingly updated voice spacings
    ArrayList<List<ElementSpacing>> optimalMeasureElementsSpacingsByStaff = alist();
    for (int iStaff : range(column)) {
        context.mp = MP.atMeasure(iStaff, measureIndex);
        List<ElementSpacing> measureSpacing = measureElementsSpacer.compute(context, createLeading, voiceSpacingsByStaff.get(iStaff), notations);
        optimalMeasureElementsSpacingsByStaff.add(measureSpacing);
    }
    // compute the common beat offsets of this measure column
    Fraction measureBeats = context.score.getMeasureBeats(measureIndex);
    VoiceSpacingsByStaff voiceSpacings = new VoiceSpacingsByStaff(voiceSpacingsByStaff);
    List<BeatOffset> beatOffsets = voicesBeatOffsetter.compute(voiceSpacings.getAll(), measureBeats, context.settings.offsetBeatsMinimal);
    // recompute beat offsets with respect to barlines
    BarlinesBeatOffsetter.Result offsets = barlinesBeatOffsetter.compute(beatOffsets, columnHeader, context.score.getMaxIS());
    beatOffsets = offsets.voiceElementOffsets;
    List<BeatOffset> barlineOffsets = offsets.barlineOffsets;
    // compute the spacings for the whole column, so that equal beats are aligned
    ArrayList<List<ElementSpacing>> alignedMeasureElementsSpacingsByStaff = alist();
    for (int iStaff : range(column)) {
        Measure measure = column.get(iStaff);
        // voice spacings
        for (int iVoice : range(measure.getVoices())) alignedVoicesSpacer.compute(voiceSpacings.get(iStaff, iVoice), beatOffsets);
        // measure elements, based on the aligned voice spacings
        context.mp = atMeasure(iStaff, measureIndex);
        alignedMeasureElementsSpacingsByStaff.add(measureElementsSpacer.compute(context, createLeading, voiceSpacings.getStaff(iStaff), notations));
    }
    // compute spacings for each staff
    List<MeasureSpacing> measureSpacings = alist(column.size());
    for (int iStaff : range(column)) {
        // create leading spacing, if needed
        LeadingSpacing leadingSpacing = null;
        if (createLeading) {
            context.mp = atBeat(iStaff, measureIndex, 0, Fraction.Companion.get_0());
            leadingSpacing = leadingSpacer.compute(context, notations);
        }
        // create measure spacing
        float interlineSpace = context.score.getInterlineSpace(iStaff);
        measureSpacings.add(new MeasureSpacing(atMeasure(iStaff, measureIndex), interlineSpace, voiceSpacings.getStaff(iStaff), alignedMeasureElementsSpacingsByStaff.get(iStaff), leadingSpacing));
    }
    context.restoreMp();
    return new ColumnSpacing(measureIndex, measureSpacings, beatOffsets, barlineOffsets);
}
Also used : LeadingSpacing(com.xenoage.zong.musiclayout.spacing.LeadingSpacing) ColumnSpacing(com.xenoage.zong.musiclayout.spacing.ColumnSpacing) Fraction(com.xenoage.utils.math.Fraction) ElementSpacing(com.xenoage.zong.musiclayout.spacing.ElementSpacing) ColumnHeader(com.xenoage.zong.core.header.ColumnHeader) Column(com.xenoage.zong.core.music.util.Column) BarlinesBeatOffsetter(com.xenoage.zong.musiclayout.spacer.beat.BarlinesBeatOffsetter) MP.atMeasure(com.xenoage.zong.core.position.MP.atMeasure) Measure(com.xenoage.zong.core.music.Measure) MeasureSpacing(com.xenoage.zong.musiclayout.spacing.MeasureSpacing) VoiceSpacingsByStaff(com.xenoage.zong.musiclayout.layouter.columnspacing.VoiceSpacingsByStaff) BeatOffset(com.xenoage.zong.musiclayout.spacing.BeatOffset) ArrayList(java.util.ArrayList) List(java.util.List) VoiceSpacing(com.xenoage.zong.musiclayout.spacing.VoiceSpacing) Voice(com.xenoage.zong.core.music.Voice)

Example 3 with ColumnHeader

use of com.xenoage.zong.core.header.ColumnHeader in project Zong by Xenoage.

the class ScoreTest method testColumnElements.

private static <T> void testColumnElements(List<Tuple2<MP, T>> expectedElements, Score score, BiFunction<ColumnHeader, Fraction, T> getElementAtBeat) {
    for (Tuple2<MP, T> expectedElement : expectedElements) {
        MP mp = expectedElement.get1();
        ColumnHeader columnHeader = score.getColumnHeader(mp.measure);
        T element = getElementAtBeat.apply(columnHeader, mp.beat);
        assertNotNull("" + mp, element);
        assertEquals("" + mp, expectedElement.get2(), element);
    }
}
Also used : ColumnHeader(com.xenoage.zong.core.header.ColumnHeader) MP(com.xenoage.zong.core.position.MP)

Example 4 with ColumnHeader

use of com.xenoage.zong.core.header.ColumnHeader in project Zong by Xenoage.

the class VoltaStamper method stampSystem.

/**
 * Creates all volta stampings in the given system, including the voltas which
 * are still open from the last system.
 * @param openVolta  input and output parameter: voltas, which are still open from the
 *                   last system. After the method returns, it contains the voltas which
 *                   are still open after this system
 */
public List<VoltaStamping> stampSystem(StaffStamping systemFirstStaff, OpenVolta openVolta, ScoreHeader header, FormattedTextStyle textStyle) {
    List<VoltaStamping> ret = alist();
    // stamp open volta
    if (openVolta.volta != null) {
        ret.add(stamp(openVolta.volta.element, systemFirstStaff, textStyle));
    }
    // stamp voltas beginning in this system
    for (int iMeasure : systemFirstStaff.system.getMeasures()) {
        ColumnHeader columnHeader = header.getColumnHeader(iMeasure);
        if (columnHeader.getVolta() != null) {
            ret.add(stamp(columnHeader.getVolta(), systemFirstStaff, textStyle));
        }
    }
    // remember open volta
    int systemEndMeasureIndex = systemFirstStaff.system.getEndMeasure();
    if (ret.size() > 0 && getLast(ret).element.getEndMeasureIndex() > systemEndMeasureIndex) {
        openVolta.volta = new ContinuedVolta(getLast(ret).element);
    } else {
        openVolta.volta = null;
    }
    return ret;
}
Also used : ColumnHeader(com.xenoage.zong.core.header.ColumnHeader) VoltaStamping(com.xenoage.zong.musiclayout.stampings.VoltaStamping) ContinuedVolta(com.xenoage.zong.musiclayout.continued.ContinuedVolta)

Example 5 with ColumnHeader

use of com.xenoage.zong.core.header.ColumnHeader in project Zong by Xenoage.

the class ColumnElementRemoveTest method test.

@Test
public void test() {
    Score score = ScoreFactory.create1Staff4Measures();
    CommandPerformer cmd = score.getCommandPerformer();
    ColumnHeader column2 = score.getColumnHeader(2);
    // write middle barline
    Barline b = Barline.Companion.barline(BarlineStyle.LightHeavy);
    cmd.execute(new ColumnElementWrite(b, column2, Companion.fr(1, 4), null));
    // remove it
    cmd.execute(new ColumnElementRemove(column2, b));
    assertEquals(0, column2.getMiddleBarlines().size());
    // undo. should be here again
    cmd.undo();
    assertEquals(b, column2.getMiddleBarlines().get(Companion.fr(1, 4)));
}
Also used : Score(com.xenoage.zong.core.Score) ColumnHeader(com.xenoage.zong.core.header.ColumnHeader) Barline(com.xenoage.zong.core.music.barline.Barline) CommandPerformer(com.xenoage.utils.document.command.CommandPerformer) Test(org.junit.Test)

Aggregations

ColumnHeader (com.xenoage.zong.core.header.ColumnHeader)13 Score (com.xenoage.zong.core.Score)7 Test (org.junit.Test)6 Barline (com.xenoage.zong.core.music.barline.Barline)3 CommandPerformer (com.xenoage.utils.document.command.CommandPerformer)2 Measure (com.xenoage.zong.core.music.Measure)2 TraditionalKey (com.xenoage.zong.core.music.key.TraditionalKey)2 MP (com.xenoage.zong.core.position.MP)2 BeatOffset (com.xenoage.zong.musiclayout.spacing.BeatOffset)2 Paint (android.graphics.Paint)1 Fraction (com.xenoage.utils.math.Fraction)1 Point2f (com.xenoage.utils.math.geom.Point2f)1 Size2f (com.xenoage.utils.math.geom.Size2f)1 MeasureNumbering (com.xenoage.zong.core.format.MeasureNumbering)1 PageFormat (com.xenoage.zong.core.format.PageFormat)1 PageMargins (com.xenoage.zong.core.format.PageMargins)1 ScoreFormat (com.xenoage.zong.core.format.ScoreFormat)1 SystemLayout (com.xenoage.zong.core.format.SystemLayout)1 ScoreHeader (com.xenoage.zong.core.header.ScoreHeader)1 MusicContext (com.xenoage.zong.core.music.MusicContext)1