Search in sources :

Example 1 with Lyric

use of com.xenoage.zong.core.music.lyric.Lyric in project Zong by Xenoage.

the class ChordNotator method compute.

public ChordNotation compute(Chord chord, Context context, @MaybeNull Notations notations) {
    Score score = context.score;
    float interlineSpace = score.getInterlineSpace(context.mp);
    FontInfo lyricsFont = score.getFormat().getLyricFont();
    MusicContext mc = score.getMusicContext(context.mp, BeforeOrAt, Before);
    // grace or normal chord?
    boolean grace = chord.isGrace();
    ChordWidths chordWidths = (grace ? context.settings.graceChordWidths : context.settings.chordWidths);
    ChordSpacings spacings = (grace ? context.settings.spacings.graceChordSpacings : context.settings.spacings.normalChordSpacings);
    // use or compute stem direction
    StemDirection stemDirection = chord.getStem().getDirection();
    if (stemDirection == StemDirection.Default) {
        // if stem direction was not computed yet, compute it now
        if (notations != null)
            stemDirection = notations.getChord(chord).stemDirection;
        if (stemDirection == StemDirection.Default) {
            Map<Chord, StemDirection> computedStems = stemDirector.compute(chord);
            stemDirection = computedStems.get(chord);
            // also remember the other computed stems
            if (notations != null)
                for (Chord computedChord : computedStems.keySet()) notations.getChord(computedChord).stemDirection = computedStems.get(computedChord);
        }
    }
    // notes displacement
    NotesNotation notes = notesNotator.compute(chord, stemDirection, chordWidths, mc);
    float leftSuspendedWidth = (notes.leftSuspended ? notes.noteheadWidthIs : 0);
    // accidentals
    AccidentalsNotation accs = accidentalsNotator.compute(chord, notes, chordWidths, mc);
    // symbol's width: width of the noteheads and dots
    float symbolWidth = notes.widthIs - leftSuspendedWidth;
    float frontGap = accs.widthIs + leftSuspendedWidth;
    // rear gap: empty duration-dependent space behind the chord minus the symbol's width
    float rearGap = spacings.getWidth(chord.getDisplayedDuration()) - symbolWidth;
    // lyric width
    float lyricWidth = 0;
    TextMeasurer textMeasurer = platformUtils().getTextMeasurer();
    for (Lyric lyric : chord.getLyrics()) {
        if (lyric != null && lyric.getText() != null) {
            // width of lyric in interline spaces
            FormattedText lyricText = styleText(lyric.getText(), new FormattedTextStyle(lyricsFont));
            float l = lyricText.getWidth() / interlineSpace;
            // for start and end syllable, request "-" more space, for middle syllables "--"
            // TODO: unsymmetric - start needs space on the right, end on the left, ...
            SyllableType lyricType = lyric.getSyllableType();
            if (lyricType == SyllableType.Begin || lyricType == SyllableType.End) {
                l += textMeasurer.measure(lyricsFont, "-").getWidth() / interlineSpace;
            } else if (lyricType == SyllableType.Middle) {
                l += textMeasurer.measure(lyricsFont, "--").getWidth() / interlineSpace;
            }
            // save width of the widest lyric
            lyricWidth = Math.max(lyricWidth, l);
        }
    }
    // compute length of the stem (if any)
    float scaling = grace ? context.settings.scalingGrace : 1;
    StemNotation stem = stemNotator.compute(chord.getStem(), notes.getLps(), stemDirection, context.mp.getStaff(), Companion.staffLines(mc.getLinesCount()), scaling);
    // compute articulations
    ArticulationsNotation arts = articulationsNotator.compute(chord, stemDirection, notes, mc.getLinesCount());
    return new ChordNotation(chord, chord.getMP(), new ElementWidth(frontGap, symbolWidth, rearGap, lyricWidth), context.mp.getStaff(), notes, stemDirection, stem, accs, arts);
}
Also used : ElementWidth(com.xenoage.zong.musiclayout.spacing.ElementWidth) ChordNotation(com.xenoage.zong.musiclayout.notation.ChordNotation) FormattedTextStyle(com.xenoage.zong.core.text.FormattedTextStyle) FormattedText(com.xenoage.zong.core.text.FormattedText) MusicContext(com.xenoage.zong.core.music.MusicContext) StemNotation(com.xenoage.zong.musiclayout.notation.chord.StemNotation) Score(com.xenoage.zong.core.Score) ArticulationsNotation(com.xenoage.zong.musiclayout.notation.chord.ArticulationsNotation) TextMeasurer(com.xenoage.utils.font.TextMeasurer) ChordWidths(com.xenoage.zong.musiclayout.settings.ChordWidths) AccidentalsNotation(com.xenoage.zong.musiclayout.notation.chord.AccidentalsNotation) Lyric(com.xenoage.zong.core.music.lyric.Lyric) ChordSpacings(com.xenoage.zong.musiclayout.settings.ChordSpacings) SyllableType(com.xenoage.zong.core.music.lyric.SyllableType) NotesNotation(com.xenoage.zong.musiclayout.notation.chord.NotesNotation) FontInfo(com.xenoage.utils.font.FontInfo) StemDirection(com.xenoage.zong.core.music.chord.StemDirection) Chord(com.xenoage.zong.core.music.chord.Chord)

Example 2 with Lyric

use of com.xenoage.zong.core.music.lyric.Lyric in project Zong by Xenoage.

the class ChordStamper method stampAll.

/**
 * Returns all the stampings for the given {@link Chord}, including beams,
 * tuplets, slurs and other attachments.
 *
 * The given {@link OpenSlursCache},
 * {@link OpenLyricsCache}, {@link LastLyrics} and {@link OpenTupletsCache} may be modified.
 */
public List<Stamping> stampAll(ChordNotation chord, float xMm, BeamSpacing beam, StaffStampings staffStampings, StamperContext context, FormattedTextStyle defaultLyricStyle, OpenSlursCache openSlursCache, OpenLyricsCache openLyricsCache, LastLyrics lastLyrics, OpenTupletsCache openTupletsCache) {
    List<Stamping> ret = alist();
    Chord element = chord.getElement();
    int staffIndex = context.staffIndex;
    int systemIndex = context.systemIndex;
    // noteheads, leger lines, dots, accidentals, stem, flags, articulations
    ChordStampings chordSt = stampCore(chord, xMm, context);
    chordSt.addAllTo(ret);
    // beam
    if (beam != null) {
        // stamp the whole beam (when we find the beginning of the beam)
        // TIDY: create/store beam stampings elsewhere?
        Beam beamElement = beam.notation.element;
        int chordIndex = beamElement.getWaypointIndex(element);
        if (chordIndex == 0) {
            ret.addAll(beamStamper.stamp(beam, context.getCurrentStaffStamping()));
        }
    }
    // ties and slurs
    for (Slur slur : element.getSlurs()) {
        SlurWaypoint wp = slur.getWaypoint(element);
        WaypointPosition pos = slur.getWaypointPosition(element);
        // TODO: choose top/bottom
        int noteIndex = notNull(wp.getNoteIndex(), 0);
        NoteheadStamping notehead = chordSt.noteheads[noteIndex];
        // define the placement: above or below (TODO: better strategy)
        VSide side = slurStamper.getSide(slur);
        // compute position
        val staff = staffStampings.get(systemIndex, notehead.parentStaff.staffIndex);
        val slurCache = openSlursCache.getOrCreate(slur);
        float distanceIs = slurStamper.getAdditionalDistanceIs(chord, slur.getSide());
        SP defaultSp = sp(notehead.position.xMm, notehead.position.lp + side.getDir() * distanceIs * 2);
        if (pos == WaypointPosition.Start)
            slurCache.setStart(defaultSp, staff, systemIndex);
        else
            slurCache.setStop(defaultSp, staff, systemIndex);
    }
    // lyric
    List<Lyric> lyrics = element.getLyrics();
    if (lyrics.size() > 0) {
        float baseLine = -10;
        for (Lyric lyric : lyrics) {
            if (lyric != null) {
                SyllableType lyricType = lyric.getSyllableType();
                StaffTextStamping lastLyric = lastLyrics.get(staffIndex, lyric.getVerse());
                if (lyricType == SyllableType.Extend) {
                    // extend
                    if (// TODO: frame breaks...
                    lastLyric != null) {
                        // remember it
                        openLyricsCache.setUnderscore((Lyric) lastLyric.getElement(), lastLyric, chordSt.noteheads[0], /* TODO*/
                        staffIndex);
                    }
                } else {
                    // normal lyric
                    // create text stamping
                    StaffTextStamping sts = lyricStamper.createSyllableStamping(lyric, defaultLyricStyle, context.getCurrentStaffStamping(), chordSt.noteheads[0].position.xMm, baseLine);
                    ret.add(sts);
                    // when middle or end syllable, add a hypen between the preceding syllable and this syllable
                    if (// TODO: frame breaks...
                    lastLyric != null) {
                        if (lyricType == SyllableType.Middle || lyricType == SyllableType.End) {
                            StaffTextStamping hyphenStamping = lyricStamper.createHyphenStamping(lastLyric, sts, defaultLyricStyle);
                            ret.add(hyphenStamping);
                        }
                    }
                    // remember this lyric as the currently last one in the current staff and verse
                    lastLyrics.set(staffIndex, lyric.getVerse(), sts);
                }
            }
            baseLine += -5;
        }
    }
    // directions
    ret.addAll(directionStamper.stampForChord(chordSt, context.layouter.symbols));
    // tuplet
    Tuplet tuplet = element.getTuplet();
    if (tuplet != null) {
        openTupletsCache.addChord(element, tuplet, chordSt);
    }
    return ret;
}
Also used : lombok.val(lombok.val) WaypointPosition(com.xenoage.zong.core.music.WaypointPosition) SlurWaypoint(com.xenoage.zong.core.music.slur.SlurWaypoint) SlurWaypoint(com.xenoage.zong.core.music.slur.SlurWaypoint) VSide(com.xenoage.utils.math.VSide) Beam(com.xenoage.zong.core.music.beam.Beam) Tuplet(com.xenoage.zong.core.music.tuplet.Tuplet) Slur(com.xenoage.zong.core.music.slur.Slur) Lyric(com.xenoage.zong.core.music.lyric.Lyric) SyllableType(com.xenoage.zong.core.music.lyric.SyllableType) Chord(com.xenoage.zong.core.music.chord.Chord) ChordStampings(com.xenoage.zong.musiclayout.layouter.scoreframelayout.util.ChordStampings) SP(com.xenoage.zong.core.music.format.SP)

Example 3 with Lyric

use of com.xenoage.zong.core.music.lyric.Lyric in project Zong by Xenoage.

the class LyricReader method readLyrics.

private List<Lyric> readLyrics() {
    // not supported yet: in MusicXML also rests can have lyrics. see measure 36 in Echigo-Jishi
    List<Lyric> ret = alist();
    for (MxlNote mxlNote : mxlNotes) {
        for (MxlLyric mxlLyric : it(mxlNote.getLyrics())) {
            int verse = readVerse(mxlLyric);
            MxlLyricContentType mxlLCType = mxlLyric.getContent().getLyricContentType();
            if (mxlLCType == MxlLyricContentType.SyllabicText) {
                MxlSyllabicText mxlSyllabicText = (MxlSyllabicText) mxlLyric.getContent();
                SyllableType syllableType = readSyllableType(mxlLyric);
                // the next element must be the text element
                ret.add(new Lyric(Companion.ut(mxlSyllabicText.getText().getValue()), syllableType, verse));
            } else if (mxlLCType == MxlLyricContentType.Extend) {
                // extend - TODO: extension to next chord!
                ret.add(Lyric.Companion.lyricExtend(verse));
            }
        }
    }
    return ret;
}
Also used : MxlLyric(com.xenoage.zong.musicxml.types.MxlLyric) MxlLyric(com.xenoage.zong.musicxml.types.MxlLyric) Lyric(com.xenoage.zong.core.music.lyric.Lyric) SyllableType(com.xenoage.zong.core.music.lyric.SyllableType) MxlSyllabicText(com.xenoage.zong.musicxml.types.MxlSyllabicText) MxlNote(com.xenoage.zong.musicxml.types.MxlNote) MxlLyricContentType(com.xenoage.zong.musicxml.types.choice.MxlLyricContent.MxlLyricContentType)

Aggregations

Lyric (com.xenoage.zong.core.music.lyric.Lyric)3 SyllableType (com.xenoage.zong.core.music.lyric.SyllableType)3 Chord (com.xenoage.zong.core.music.chord.Chord)2 FontInfo (com.xenoage.utils.font.FontInfo)1 TextMeasurer (com.xenoage.utils.font.TextMeasurer)1 VSide (com.xenoage.utils.math.VSide)1 Score (com.xenoage.zong.core.Score)1 MusicContext (com.xenoage.zong.core.music.MusicContext)1 WaypointPosition (com.xenoage.zong.core.music.WaypointPosition)1 Beam (com.xenoage.zong.core.music.beam.Beam)1 StemDirection (com.xenoage.zong.core.music.chord.StemDirection)1 SP (com.xenoage.zong.core.music.format.SP)1 Slur (com.xenoage.zong.core.music.slur.Slur)1 SlurWaypoint (com.xenoage.zong.core.music.slur.SlurWaypoint)1 Tuplet (com.xenoage.zong.core.music.tuplet.Tuplet)1 FormattedText (com.xenoage.zong.core.text.FormattedText)1 FormattedTextStyle (com.xenoage.zong.core.text.FormattedTextStyle)1 ChordStampings (com.xenoage.zong.musiclayout.layouter.scoreframelayout.util.ChordStampings)1 ChordNotation (com.xenoage.zong.musiclayout.notation.ChordNotation)1 AccidentalsNotation (com.xenoage.zong.musiclayout.notation.chord.AccidentalsNotation)1