Search in sources :

Example 1 with Notation

use of com.xenoage.zong.musiclayout.notation.Notation in project Zong by Xenoage.

the class MeasureElementsSpacer method compute.

List<ElementSpacing> compute(BeatEList<Clef> clefs, @MaybeEmpty BeatEList<Key> keys, @MaybeNull TimeSignature time, boolean existsLeadingSpacing, List<VoiceSpacing> voiceSpacings, int staff, Notations notations, LayoutSettings layoutSettings) {
    Key key0 = null;
    if (keys.size() > 0 && keys.getFirst().getBeat().equals(Companion.get_0()))
        key0 = keys.getFirst().getElement();
    if (key0 == null && time == null && (clefs == null || clefs.size() == 0)) {
        // nothing to do
        return empty;
    }
    ArrayList<ElementSpacing> ret = alist();
    float startOffset = layoutSettings.offsetMeasureStart;
    // key and time
    // ************
    boolean isKey = !existsLeadingSpacing && key0 instanceof TraditionalKey;
    boolean isTime = time != null;
    if (isKey || isTime) {
        float currentOffset = startOffset;
        // ***
        if (isKey) {
            Notation keyNotation = notations.get(key0, staff);
            ret.add(new SimpleSpacing(keyNotation, Companion.get_0(), startOffset));
            currentOffset += keyNotation.getWidth().getUsedWidth();
        }
        // ****
        if (time != null) {
            Notation timeNotation = notations.get(time, staff);
            ret.add(new SimpleSpacing(timeNotation, Companion.get_0(), currentOffset + timeNotation.getWidth().symbolWidth / 2));
            currentOffset += timeNotation.getWidth().getUsedWidth();
        }
        // move voice elements, if not enough space before first voice element
        ElementSpacing leftSE = getFirstElementSpacing(voiceSpacings);
        if (leftSE != null) {
            float leftSEx = getLeftX(leftSE);
            // existing space
            float ES = leftSEx;
            // additional needed space
            float AS = currentOffset - ES;
            if (AS > 0) {
                shift(voiceSpacings, AS);
                startOffset += AS;
            }
        }
    }
    // voice 2:       1             o
    if (clefs != null) {
        for (BeatE<Clef> ME : clefs) {
            Fraction MEb = ME.getBeat();
            Notation MEnotation = notations.get(ME.getElement());
            float MEwidth = MEnotation.getWidth().getWidth();
            // if there is a leading spacing, ignore elements at beat 0
            if (existsLeadingSpacing && !MEb.isGreater0())
                continue;
            // find VE1 and VE2 for the current element
            ElementSpacing[] ses = getNearestSpacingElements(MEb, voiceSpacings);
            ElementSpacing VE1 = ses[0], VE2 = ses[1];
            // if VE1 is unknown, use startOffset. if VE2 is unknown, ignore this element
            float VE1x = (VE1 != null ? getRightX(VE1) : startOffset);
            if (VE2 == null)
                continue;
            float VE2x = getLeftX(VE2);
            // existing space
            float ES = VE2x - VE1x - 2 * layoutSettings.spacings.widthDistanceMin;
            if (ES < MEwidth) {
                // additional space needed
                float AS = MEwidth - ES;
                // move all elements at or after ME.beat
                VE2x += AS;
                shiftAfterBeat(voiceSpacings, AS, MEb);
            }
            // add measure element
            float MEx = VE2x - layoutSettings.spacings.widthDistanceMin - MEwidth / 2;
            ret.add(new SimpleSpacing(MEnotation, ME.getBeat(), MEx));
        }
    }
    ret.trimToSize();
    return ret;
}
Also used : ElementSpacing(com.xenoage.zong.musiclayout.spacing.ElementSpacing) SimpleSpacing(com.xenoage.zong.musiclayout.spacing.SimpleSpacing) Clef(com.xenoage.zong.core.music.clef.Clef) Fraction(com.xenoage.utils.math.Fraction) TraditionalKey(com.xenoage.zong.core.music.key.TraditionalKey) Notation(com.xenoage.zong.musiclayout.notation.Notation) TraditionalKey(com.xenoage.zong.core.music.key.TraditionalKey) Key(com.xenoage.zong.core.music.key.Key)

Example 2 with Notation

use of com.xenoage.zong.musiclayout.notation.Notation in project Zong by Xenoage.

the class MeasureStamper method stampMeasure.

/**
 * Stamps all {@link MeasureElement}s of the given measure (but not the leading elements).
 * @param measureXMm  the horizontal position on the staff in mm, where the measure
 *                    starts (after leading spacing).
 */
public List<Stamping> stampMeasure(MeasureSpacing measure, float measureXMm, StamperContext context) {
    List<Stamping> ret = alist();
    for (ElementSpacing element : measure.elements) {
        MusicElement me = element.getElement();
        if (me != null) {
            Notation notation = context.getNotation(me);
            float xMm = measureXMm + element.xIs * measure.interlineSpace;
            ret.add(stamp(notation, xMm, context));
        }
    }
    return ret;
}
Also used : ElementSpacing(com.xenoage.zong.musiclayout.spacing.ElementSpacing) Stamping(com.xenoage.zong.musiclayout.stampings.Stamping) MusicElement(com.xenoage.zong.core.music.MusicElement) Notation(com.xenoage.zong.musiclayout.notation.Notation) ClefNotation(com.xenoage.zong.musiclayout.notation.ClefNotation) TimeNotation(com.xenoage.zong.musiclayout.notation.TimeNotation) TraditionalKeyNotation(com.xenoage.zong.musiclayout.notation.TraditionalKeyNotation)

Example 3 with Notation

use of com.xenoage.zong.musiclayout.notation.Notation in project Zong by Xenoage.

the class VoiceStamper method stampVoice.

public List<Stamping> stampVoice(VoiceSpacing voice, float voiceXMm, StaffStampings staffStampings, boolean stampLeadingRests, StamperContext context, // TODO:
FormattedTextStyle defaultLyricStyle, Map<Beam, BeamSpacing> beams, OpenSlursCache openCurvedLinesCache, OpenLyricsCache openLyricsCache, LastLyrics lastLyrics, OpenTupletsCache openTupletsCache) {
    List<Stamping> ret = alist();
    // create the voice elements
    boolean onlyRestsSoFar = true;
    for (ElementSpacing spacingElement : voice.elements) {
        MusicElement element = spacingElement.getElement();
        if (element != null) /* TODO && (stampRests || !(element instanceof Rest)) */
        {
            Notation notation = context.getNotation(element);
            float xMm = voiceXMm + spacingElement.xIs * voice.interlineSpace;
            if (element instanceof Chord) {
                // chord
                onlyRestsSoFar = false;
                Chord chord = (Chord) element;
                BeamSpacing beam = beams.get(chord.getBeam());
                ret.addAll(chordStamper.stampAll((ChordNotation) spacingElement.getNotation(), xMm, beam, staffStampings, context, defaultLyricStyle, openCurvedLinesCache, openLyricsCache, lastLyrics, openTupletsCache));
            } else if (spacingElement instanceof RestSpacing) {
                // rest
                if (false == onlyRestsSoFar || stampLeadingRests) {
                    // not a leading rest, or a leading rest which should be stamped
                    ret.add(elementStamper.createRestStamping((RestSpacing) spacingElement, xMm, context));
                }
            } else {
                throw new IllegalArgumentException("Notation not supported: " + notation);
            }
        }
    }
    return ret;
}
Also used : ElementSpacing(com.xenoage.zong.musiclayout.spacing.ElementSpacing) Stamping(com.xenoage.zong.musiclayout.stampings.Stamping) BeamSpacing(com.xenoage.zong.musiclayout.spacing.BeamSpacing) ChordNotation(com.xenoage.zong.musiclayout.notation.ChordNotation) MusicElement(com.xenoage.zong.core.music.MusicElement) RestSpacing(com.xenoage.zong.musiclayout.spacing.RestSpacing) Notation(com.xenoage.zong.musiclayout.notation.Notation) ChordNotation(com.xenoage.zong.musiclayout.notation.ChordNotation) Chord(com.xenoage.zong.core.music.chord.Chord)

Example 4 with Notation

use of com.xenoage.zong.musiclayout.notation.Notation in project Zong by Xenoage.

the class SingleVoiceSpacer method compute.

VoiceSpacing compute(Voice voice, float interlineSpace, Fraction measureBeats, int staffLinesCount, Notations notations, LayoutSettings layoutSettings) {
    LinkedList<ElementSpacing> ret = llist();
    // special case: no elements in the measure.
    if (voice.getElements().size() == 0) {
        return new VoiceSpacing(voice, interlineSpace, alist((ElementSpacing) new BorderSpacing(Fraction.Companion.get_0(), 0), new BorderSpacing(measureBeats, layoutSettings.spacings.widthMeasureEmpty)));
    }
    // we compute the spacings in reverse order. this is easier, since grace chords
    // use shared space when possible, but are aligned to the right. so we begin
    // at position 0, and create the spacings in reverse direction (thus we find negative positions).
    // at the end, we shift the voice spacing to the right to be aligned at the left measure border,
    // which is position 0.
    // last symbol offset:
    // real offset where the last element's symbol started
    // since we do not know the right border yet, we start at 0
    float lastSymbolOffset = 0;
    // front gap offset:
    // offset where the last element (including front gap) started.
    float lastFrontGapOffset = lastSymbolOffset;
    // last full element offset:
    // lastSymbolOffset of the last full (non-grace) element
    float lastFullSymbolOffset = lastSymbolOffset;
    // at last beat
    Fraction curBeat = voice.getFilledBeats();
    ret.addFirst(new BorderSpacing(curBeat, lastFrontGapOffset));
    // iterate through the elements in reverse order
    for (VoiceElement element : Companion.reverseIt(voice.getElements())) {
        // get the notation
        Notation notation = notations.get(element);
        if (notation == null)
            throw new IllegalStateException("No notation for element " + element);
        // get the width of the element (front gap, symbol's width, rear gap, lyric's width)
        ElementWidth elementWidth = notation.getWidth();
        // add spacing for voice element
        float symbolOffset;
        boolean grace = !element.getDuration().isGreater0();
        if (!grace) {
            // full element
            // share this rear gap and the front gap of the following
            // element + the space of following grace elements, when possible
            // (but use at least minimal distance)
            symbolOffset = Math.min(lastFrontGapOffset - layoutSettings.spacings.widthDistanceMin, lastFullSymbolOffset - elementWidth.rearGap) - elementWidth.symbolWidth;
            lastFullSymbolOffset = symbolOffset;
            // update beat cursor
            curBeat = curBeat.sub(element.getDuration());
        } else {
            // grace element
            // share this rear gap and the front gap of the following element, when possible
            symbolOffset = Math.min(lastFrontGapOffset, lastSymbolOffset - elementWidth.rearGap) - elementWidth.symbolWidth;
        }
        ElementSpacing elementSpacing = null;
        if (notation instanceof RestNotation) {
            // rest spacing
            elementSpacing = restSpacer.compute((RestNotation) notation, curBeat, symbolOffset, staffLinesCount);
        } else {
            // chord spacing
            elementSpacing = new ChordSpacing((ChordNotation) notation, curBeat, symbolOffset);
        }
        ret.addFirst(elementSpacing);
        lastFrontGapOffset = symbolOffset - elementWidth.frontGap;
        lastSymbolOffset = symbolOffset;
    }
    // shift spacings to the right
    float shift = (-lastFrontGapOffset) + layoutSettings.offsetMeasureStart;
    for (ElementSpacing e : ret) e.xIs += shift;
    return new VoiceSpacing(voice, interlineSpace, ilist(ret));
}
Also used : ElementWidth(com.xenoage.zong.musiclayout.spacing.ElementWidth) ChordNotation(com.xenoage.zong.musiclayout.notation.ChordNotation) RestNotation(com.xenoage.zong.musiclayout.notation.RestNotation) Fraction(com.xenoage.utils.math.Fraction) Notation(com.xenoage.zong.musiclayout.notation.Notation) RestNotation(com.xenoage.zong.musiclayout.notation.RestNotation) ChordNotation(com.xenoage.zong.musiclayout.notation.ChordNotation) ElementSpacing(com.xenoage.zong.musiclayout.spacing.ElementSpacing) ChordSpacing(com.xenoage.zong.musiclayout.spacing.ChordSpacing) BorderSpacing(com.xenoage.zong.musiclayout.spacing.BorderSpacing) VoiceElement(com.xenoage.zong.core.music.VoiceElement) VoiceSpacing(com.xenoage.zong.musiclayout.spacing.VoiceSpacing)

Example 5 with Notation

use of com.xenoage.zong.musiclayout.notation.Notation in project Zong by Xenoage.

the class Notator method compute.

/**
 * Computes the {@link Notation} of the given element.
 */
@MaybeNull
private Notation compute(MPElement element, Context context, Notations notations) {
    ElementNotator notator = notators.get(element.getMusicElementType());
    if (// element needs no notation
    notator == null)
        return null;
    Notation notation = notator.compute(element, context, notations);
    return notation;
}
Also used : Notation(com.xenoage.zong.musiclayout.notation.Notation) MaybeNull(com.xenoage.utils.annotations.MaybeNull)

Aggregations

Notation (com.xenoage.zong.musiclayout.notation.Notation)6 ElementSpacing (com.xenoage.zong.musiclayout.spacing.ElementSpacing)5 MusicElement (com.xenoage.zong.core.music.MusicElement)3 Stamping (com.xenoage.zong.musiclayout.stampings.Stamping)3 Fraction (com.xenoage.utils.math.Fraction)2 ChordNotation (com.xenoage.zong.musiclayout.notation.ChordNotation)2 ClefNotation (com.xenoage.zong.musiclayout.notation.ClefNotation)2 TimeNotation (com.xenoage.zong.musiclayout.notation.TimeNotation)2 TraditionalKeyNotation (com.xenoage.zong.musiclayout.notation.TraditionalKeyNotation)2 MaybeNull (com.xenoage.utils.annotations.MaybeNull)1 VoiceElement (com.xenoage.zong.core.music.VoiceElement)1 Chord (com.xenoage.zong.core.music.chord.Chord)1 Clef (com.xenoage.zong.core.music.clef.Clef)1 Key (com.xenoage.zong.core.music.key.Key)1 TraditionalKey (com.xenoage.zong.core.music.key.TraditionalKey)1 RestNotation (com.xenoage.zong.musiclayout.notation.RestNotation)1 BeamSpacing (com.xenoage.zong.musiclayout.spacing.BeamSpacing)1 BorderSpacing (com.xenoage.zong.musiclayout.spacing.BorderSpacing)1 ChordSpacing (com.xenoage.zong.musiclayout.spacing.ChordSpacing)1 ElementWidth (com.xenoage.zong.musiclayout.spacing.ElementWidth)1