private int width; /** Width of symbol */ /** * Create a new AccidSymbol with the given accidental, that is * displayed at the given note in the given clef. */ public AccidSymbol(Accid accid, WhiteNote note, Clef clef) { this.accid = accid; this.whitenote = note; this.clef = clef; width = MinWidth; }
/** Draw the Chord Symbol: * - Draw the accidental symbols. * - Draw the black circle notes. * - Draw the stems. * @param ytop The ylocation (in pixels) where the top of the staff starts. */ public override void Draw(Graphics g, Pen pen, int ytop) { /* Align the chord to the right */ g.TranslateTransform(Width - MinWidth, 0); /* Draw the accidentals. */ WhiteNote topstaff = WhiteNote.Top(clef); int xpos = DrawAccid(g, pen, ytop); /* Draw the notes */ g.TranslateTransform(xpos, 0); DrawNotes(g, pen, ytop, topstaff); if (sheetmusic != null && sheetmusic.ShowNoteLetters != 0) { DrawNoteLetters(g, pen, ytop, topstaff); } /* Draw the stems */ if (stem1 != null) { stem1.Draw(g, pen, ytop, topstaff); } if (stem2 != null) { stem2.Draw(g, pen, ytop, topstaff); } g.TranslateTransform(-xpos, 0); g.TranslateTransform(-(Width - MinWidth), 0); }
private int GetAboveStaff() { /* Find the topmost note in the chord */ WhiteNote topnote = notedata[notedata.Length - 1].whitenote; /* The stem.End is the note position where the stem ends. * Check if the stem end is higher than the top note. */ if (stem1 != null) { topnote = WhiteNote.Max(topnote, stem1.End); } if (stem2 != null) { topnote = WhiteNote.Max(topnote, stem2.End); } int dist = topnote.Dist(WhiteNote.Top(clef)) * SheetMusic.NoteHeight / 2; int result = 0; if (dist > 0) { result = dist; } /* Check if any accidental symbols extend above the staff */ foreach (AccidSymbol symbol in accidsymbols) { if (symbol.AboveStaff > result) { result = symbol.AboveStaff; } } return(result); }
/** Draw this stem. * @param ytop The y location (in pixels) where the top of the staff starts. * @param topstaff The note at the top of the staff. */ public void Draw(Graphics g, Pen pen, int ytop, WhiteNote topstaff) { if (duration == NoteDuration.Whole) { return; } DrawVerticalLine(g, pen, ytop, topstaff); if (duration == NoteDuration.Quarter || duration == NoteDuration.DottedQuarter || duration == NoteDuration.Half || duration == NoteDuration.DottedHalf || receiver_in_pair) { return; } if (pair != null) { DrawHorizBarStem(g, pen, ytop, topstaff); } else { DrawCurvyStem(g, pen, ytop, topstaff); } }
/** Calculate the vertical position (white note key) where * the stem ends */ public WhiteNote CalculateEnd() { if (direction == Up) { WhiteNote w = top; w = w.Add(6); if (duration == NoteDuration.Sixteenth) { w = w.Add(2); } else if (duration == NoteDuration.ThirtySecond) { w = w.Add(4); } return(w); } else if (direction == Down) { WhiteNote w = bottom; w = w.Add(-6); if (duration == NoteDuration.Sixteenth) { w = w.Add(-2); } else if (duration == NoteDuration.ThirtySecond) { w = w.Add(-4); } return(w); } else { return(null); /* Shouldn't happen */ } }
/** Draw the note letters (A, A#, Bb, etc) next to the note circles. * @param ytop The ylocation (in pixels) where the top of the staff starts. * @param topstaff The white note of the top of the staff. */ public void DrawNoteLetters(Graphics g, Pen pen, int ytop, WhiteNote topstaff) { bool overlap = NotesOverlap(notedata, 0, notedata.Length); pen.Width = 1; foreach (NoteData note in notedata) { if (!note.leftside) { /* There's not enought pixel room to show the letter */ continue; } /* Get the x,y position to draw the note */ int ynote = ytop + topstaff.Dist(note.whitenote) * SheetMusic.NoteHeight / 2; /* Draw the letter to the right side of the note */ int xnote = SheetMusic.NoteWidth + SheetMusic.LineSpace / 4; if (note.duration == NoteDuration.DottedHalf || note.duration == NoteDuration.DottedQuarter || note.duration == NoteDuration.DottedEighth || overlap) { xnote += SheetMusic.NoteWidth / 2; } g.DrawString(NoteName(note.number, note.whitenote), SheetMusic.LetterFont, Brushes.Black, xnote, ynote - SheetMusic.NoteHeight / 2); } }
/** Change the direction of the stem. This function is called by * ChordSymbol.MakePair(). When two chords are joined by a horizontal * beam, their stems must point in the same direction (up or down). */ public void ChangeDirection(int newdirection) { direction = newdirection; if (direction == Up || notesoverlap) { side = RightSide; } else { side = LeftSide; } end = CalculateEnd(); }
BringStemsCloser(ChordSymbol[] chords) { Stem firstStem = chords[0].Stem; Stem lastStem = chords[1].Stem; /* If we're connecting a dotted 8th to a 16th, increase * the stem end of the dotted eighth. */ if (firstStem.Duration == NoteDuration.DottedEighth && lastStem.Duration == NoteDuration.Sixteenth) { if (firstStem.Direction == Stem.Up) { firstStem.End = firstStem.End.Add(2); } else { firstStem.End = firstStem.End.Add(-2); } } /* Bring the stem ends closer together */ int distance = Math.Abs(firstStem.End.Dist(lastStem.End)); if (firstStem.Direction == Stem.Up) { if (WhiteNote.Max(firstStem.End, lastStem.End) == firstStem.End) { lastStem.End = lastStem.End.Add(distance / 2); } else { firstStem.End = firstStem.End.Add(distance / 2); } } else { if (WhiteNote.Min(firstStem.End, lastStem.End) == firstStem.End) { lastStem.End = lastStem.End.Add(-distance / 2); } else { firstStem.End = firstStem.End.Add(-distance / 2); } } }
/** Draw the vertical line of the stem * @param ytop The y location (in pixels) where the top of the staff starts. * @param topstaff The note at the top of the staff. */ private void DrawVerticalLine(Graphics g, Pen pen, int ytop, WhiteNote topstaff) { int xstart; if (side == LeftSide) { xstart = SheetMusic.LineSpace / 4 + 1; } else { xstart = SheetMusic.LineSpace / 4 + SheetMusic.NoteWidth; } if (direction == Up) { int y1 = ytop + topstaff.Dist(bottom) * SheetMusic.NoteHeight / 2 + SheetMusic.NoteHeight / 4; int ystem = ytop + topstaff.Dist(end) * SheetMusic.NoteHeight / 2; g.DrawLine(pen, xstart, y1, xstart, ystem); } else if (direction == Down) { int y1 = ytop + topstaff.Dist(top) * SheetMusic.NoteHeight / 2 + SheetMusic.NoteHeight; if (side == LeftSide) { y1 = y1 - SheetMusic.NoteHeight / 4; } else { y1 = y1 - SheetMusic.NoteHeight / 2; } int ystem = ytop + topstaff.Dist(end) * SheetMusic.NoteHeight / 2 + SheetMusic.NoteHeight; g.DrawLine(pen, xstart, y1, xstart, ystem); } }
private int GetBelowStaff() { int dist = WhiteNote.Bottom(clef).Dist(whitenote) * SheetMusic.NoteHeight / 2 + SheetMusic.NoteHeight; if (accid == Accid.Sharp || accid == Accid.Natural) { dist += SheetMusic.NoteHeight; } if (dist > 0) { return(dist); } else { return(0); } }
/** Create a new stem. The top note, bottom note, and direction are * needed for drawing the vertical line of the stem. The duration is * needed to draw the tail of the stem. The overlap boolean is true * if the notes in the chord overlap. If the notes overlap, the * stem must be drawn on the right side. */ public Stem(WhiteNote bottom, WhiteNote top, NoteDuration duration, int direction, bool overlap) { this.top = top; this.bottom = bottom; this.duration = duration; this.direction = direction; this.notesoverlap = overlap; if (direction == Up || notesoverlap) { side = RightSide; } else { side = LeftSide; } end = CalculateEnd(); pair = null; width_to_pair = 0; receiver_in_pair = false; }
int GetAboveStaff() { int dist = WhiteNote.Top(clef).Dist(whitenote) * SheetMusic.NoteHeight / 2; if (accid == Accid.Sharp || accid == Accid.Natural) { dist -= SheetMusic.NoteHeight; } else if (accid == Accid.Flat) { dist -= 3 * SheetMusic.NoteHeight / 2; } if (dist < 0) { return(-dist); } else { return(0); } }
private int GetBelowStaff() { /* Find the bottom note in the chord */ WhiteNote bottomnote = notedata[0].whitenote; /* The stem.End is the note position where the stem ends. * Check if the stem end is lower than the bottom note. */ if (stem1 != null) { bottomnote = WhiteNote.Min(bottomnote, stem1.End); } if (stem2 != null) { bottomnote = WhiteNote.Min(bottomnote, stem2.End); } int dist = WhiteNote.Bottom(clef).Dist(bottomnote) * SheetMusic.NoteHeight / 2; int result = 0; if (dist > 0) { result = dist; } /* Check if any accidental symbols extend below the staff */ foreach (AccidSymbol symbol in accidsymbols) { if (symbol.BelowStaff > result) { result = symbol.BelowStaff; } } return(result); }
StemDirection(WhiteNote bottom, WhiteNote top, Clef clef) { WhiteNote middle; if (clef == Clef.Treble) { middle = new WhiteNote(WhiteNote.B, 5); } else { middle = new WhiteNote(WhiteNote.D, 3); } int dist = middle.Dist(bottom) + middle.Dist(top); if (dist >= 0) { return(Stem.Up); } else { return(Stem.Down); } }
/** Draw the symbol. * @param ytop The ylocation (in pixels) where the top of the staff starts. */ public override void Draw(Graphics g, Pen pen, int ytop) { /* Align the symbol to the right */ g.TranslateTransform(Width - MinWidth, 0); /* Store the y-pixel value of the top of the whitenote in ynote. */ int ynote = ytop + WhiteNote.Top(clef).Dist(whitenote) * SheetMusic.NoteHeight / 2; if (accid == Accid.Sharp) { DrawSharp(g, pen, ynote); } else if (accid == Accid.Flat) { DrawFlat(g, pen, ynote); } else if (accid == Accid.Natural) { DrawNatural(g, pen, ynote); } g.TranslateTransform(-(Width - MinWidth), 0); }
/** Create the Accidental symbols for this key, for * the treble and bass clefs. */ private void CreateSymbols() { int count = Math.Max(num_sharps, num_flats); treble = new AccidSymbol[count]; bass = new AccidSymbol[count]; if (count == 0) { return; } WhiteNote[] treblenotes = null; WhiteNote[] bassnotes = null; if (num_sharps > 0) { treblenotes = new WhiteNote[] { new WhiteNote(WhiteNote.F, 5), new WhiteNote(WhiteNote.C, 5), new WhiteNote(WhiteNote.G, 5), new WhiteNote(WhiteNote.D, 5), new WhiteNote(WhiteNote.A, 6), new WhiteNote(WhiteNote.E, 5) }; bassnotes = new WhiteNote[] { new WhiteNote(WhiteNote.F, 3), new WhiteNote(WhiteNote.C, 3), new WhiteNote(WhiteNote.G, 3), new WhiteNote(WhiteNote.D, 3), new WhiteNote(WhiteNote.A, 4), new WhiteNote(WhiteNote.E, 3) }; } else if (num_flats > 0) { treblenotes = new WhiteNote[] { new WhiteNote(WhiteNote.B, 5), new WhiteNote(WhiteNote.E, 5), new WhiteNote(WhiteNote.A, 5), new WhiteNote(WhiteNote.D, 5), new WhiteNote(WhiteNote.G, 4), new WhiteNote(WhiteNote.C, 5) }; bassnotes = new WhiteNote[] { new WhiteNote(WhiteNote.B, 3), new WhiteNote(WhiteNote.E, 3), new WhiteNote(WhiteNote.A, 3), new WhiteNote(WhiteNote.D, 3), new WhiteNote(WhiteNote.G, 2), new WhiteNote(WhiteNote.C, 3) }; } Accid a = Accid.None; if (num_sharps > 0) { a = Accid.Sharp; } else { a = Accid.Flat; } for (int i = 0; i < count; i++) { treble[i] = new AccidSymbol(a, treblenotes[i], Clef.Treble); bass[i] = new AccidSymbol(a, bassnotes[i], Clef.Bass); } }
/** Draw the black circle notes. * @param ytop The ylocation (in pixels) where the top of the staff starts. * @param topstaff The white note of the top of the staff. */ public void DrawNotes(Graphics g, Pen pen, int ytop, WhiteNote topstaff) { pen.Width = 1; foreach (NoteData note in notedata) { /* Get the x,y position to draw the note */ int ynote = ytop + topstaff.Dist(note.whitenote) * SheetMusic.NoteHeight / 2; int xnote = SheetMusic.LineSpace / 4; if (!note.leftside) { xnote += SheetMusic.NoteWidth; } /* Draw rotated ellipse. You must first translate (0,0) * to the center of the ellipse. */ g.TranslateTransform(xnote + SheetMusic.NoteWidth / 2 + 1, ynote - SheetMusic.LineWidth + SheetMusic.NoteHeight / 2); g.RotateTransform(-45); if (sheetmusic != null) { pen.Color = sheetmusic.NoteColor(note.number); } else { pen.Color = Color.Black; } if (note.duration == NoteDuration.Whole || note.duration == NoteDuration.Half || note.duration == NoteDuration.DottedHalf) { g.DrawEllipse(pen, -SheetMusic.NoteWidth / 2, -SheetMusic.NoteHeight / 2, SheetMusic.NoteWidth, SheetMusic.NoteHeight - 1); g.DrawEllipse(pen, -SheetMusic.NoteWidth / 2, -SheetMusic.NoteHeight / 2 + 1, SheetMusic.NoteWidth, SheetMusic.NoteHeight - 2); g.DrawEllipse(pen, -SheetMusic.NoteWidth / 2, -SheetMusic.NoteHeight / 2 + 1, SheetMusic.NoteWidth, SheetMusic.NoteHeight - 3); } else { Brush brush = Brushes.Black; if (pen.Color != Color.Black) { brush = new SolidBrush(pen.Color); } g.FillEllipse(brush, -SheetMusic.NoteWidth / 2, -SheetMusic.NoteHeight / 2, SheetMusic.NoteWidth, SheetMusic.NoteHeight - 1); if (pen.Color != Color.Black) { brush.Dispose(); } } pen.Color = Color.Black; g.DrawEllipse(pen, -SheetMusic.NoteWidth / 2, -SheetMusic.NoteHeight / 2, SheetMusic.NoteWidth, SheetMusic.NoteHeight - 1); g.RotateTransform(45); g.TranslateTransform(-(xnote + SheetMusic.NoteWidth / 2 + 1), -(ynote - SheetMusic.LineWidth + SheetMusic.NoteHeight / 2)); /* Draw a dot if this is a dotted duration. */ if (note.duration == NoteDuration.DottedHalf || note.duration == NoteDuration.DottedQuarter || note.duration == NoteDuration.DottedEighth) { g.FillEllipse(Brushes.Black, xnote + SheetMusic.NoteWidth + SheetMusic.LineSpace / 3, ynote + SheetMusic.LineSpace / 3, 4, 4); } /* Draw horizontal lines if note is above/below the staff */ WhiteNote top = topstaff.Add(1); int dist = note.whitenote.Dist(top); int y = ytop - SheetMusic.LineWidth; if (dist >= 2) { for (int i = 2; i <= dist; i += 2) { y -= SheetMusic.NoteHeight; g.DrawLine(pen, xnote - SheetMusic.LineSpace / 4, y, xnote + SheetMusic.NoteWidth + SheetMusic.LineSpace / 4, y); } } WhiteNote bottom = top.Add(-8); y = ytop + (SheetMusic.LineSpace + SheetMusic.LineWidth) * 4 - 1; dist = bottom.Dist(note.whitenote); if (dist >= 2) { for (int i = 2; i <= dist; i += 2) { y += SheetMusic.NoteHeight; g.DrawLine(pen, xnote - SheetMusic.LineSpace / 4, y, xnote + SheetMusic.NoteWidth + SheetMusic.LineSpace / 4, y); } } /* End drawing horizontal lines */ } }
/** Draw a curvy stem tail. This is only used for single chords, not chord pairs. * @param ytop The y location (in pixels) where the top of the staff starts. * @param topstaff The note at the top of the staff. */ private void DrawCurvyStem(Graphics g, Pen pen, int ytop, WhiteNote topstaff) { pen.Width = 2; int xstart = 0; if (side == LeftSide) { xstart = SheetMusic.LineSpace / 4 + 1; } else { xstart = SheetMusic.LineSpace / 4 + SheetMusic.NoteWidth; } if (direction == Up) { int ystem = ytop + topstaff.Dist(end) * SheetMusic.NoteHeight / 2; if (duration == NoteDuration.Eighth || duration == NoteDuration.DottedEighth || duration == NoteDuration.Triplet || duration == NoteDuration.Sixteenth || duration == NoteDuration.ThirtySecond) { g.DrawBezier(pen, xstart, ystem, xstart, ystem + 3 * SheetMusic.LineSpace / 2, xstart + SheetMusic.LineSpace * 2, ystem + SheetMusic.NoteHeight * 2, xstart + SheetMusic.LineSpace / 2, ystem + SheetMusic.NoteHeight * 3); } ystem += SheetMusic.NoteHeight; if (duration == NoteDuration.Sixteenth || duration == NoteDuration.ThirtySecond) { g.DrawBezier(pen, xstart, ystem, xstart, ystem + 3 * SheetMusic.LineSpace / 2, xstart + SheetMusic.LineSpace * 2, ystem + SheetMusic.NoteHeight * 2, xstart + SheetMusic.LineSpace / 2, ystem + SheetMusic.NoteHeight * 3); } ystem += SheetMusic.NoteHeight; if (duration == NoteDuration.ThirtySecond) { g.DrawBezier(pen, xstart, ystem, xstart, ystem + 3 * SheetMusic.LineSpace / 2, xstart + SheetMusic.LineSpace * 2, ystem + SheetMusic.NoteHeight * 2, xstart + SheetMusic.LineSpace / 2, ystem + SheetMusic.NoteHeight * 3); } } else if (direction == Down) { int ystem = ytop + topstaff.Dist(end) * SheetMusic.NoteHeight / 2 + SheetMusic.NoteHeight; if (duration == NoteDuration.Eighth || duration == NoteDuration.DottedEighth || duration == NoteDuration.Triplet || duration == NoteDuration.Sixteenth || duration == NoteDuration.ThirtySecond) { g.DrawBezier(pen, xstart, ystem, xstart, ystem - SheetMusic.LineSpace, xstart + SheetMusic.LineSpace * 2, ystem - SheetMusic.NoteHeight * 2, xstart + SheetMusic.LineSpace, ystem - SheetMusic.NoteHeight * 2 - SheetMusic.LineSpace / 2); } ystem -= SheetMusic.NoteHeight; if (duration == NoteDuration.Sixteenth || duration == NoteDuration.ThirtySecond) { g.DrawBezier(pen, xstart, ystem, xstart, ystem - SheetMusic.LineSpace, xstart + SheetMusic.LineSpace * 2, ystem - SheetMusic.NoteHeight * 2, xstart + SheetMusic.LineSpace, ystem - SheetMusic.NoteHeight * 2 - SheetMusic.LineSpace / 2); } ystem -= SheetMusic.NoteHeight; if (duration == NoteDuration.ThirtySecond) { g.DrawBezier(pen, xstart, ystem, xstart, ystem - SheetMusic.LineSpace, xstart + SheetMusic.LineSpace * 2, ystem - SheetMusic.NoteHeight * 2, xstart + SheetMusic.LineSpace, ystem - SheetMusic.NoteHeight * 2 - SheetMusic.LineSpace / 2); } } pen.Width = 1; }
/** Get the letter (A, A#, Bb) representing this note */ private string Letter(int notenumber, WhiteNote whitenote) { int notescale = NoteScale.FromNumber(notenumber); switch (notescale) { case NoteScale.A: return("A"); case NoteScale.B: return("B"); case NoteScale.C: return("C"); case NoteScale.D: return("D"); case NoteScale.E: return("E"); case NoteScale.F: return("F"); case NoteScale.G: return("G"); case NoteScale.Asharp: if (whitenote.Letter == WhiteNote.A) { return("A#"); } else { return("Bb"); } case NoteScale.Csharp: if (whitenote.Letter == WhiteNote.C) { return("C#"); } else { return("Db"); } case NoteScale.Dsharp: if (whitenote.Letter == WhiteNote.D) { return("D#"); } else { return("Eb"); } case NoteScale.Fsharp: if (whitenote.Letter == WhiteNote.F) { return("F#"); } else { return("Gb"); } case NoteScale.Gsharp: if (whitenote.Letter == WhiteNote.G) { return("G#"); } else { return("Ab"); } default: return(""); } }
/** Get the name for this note */ private string NoteName(int notenumber, WhiteNote whitenote) { if (sheetmusic.ShowNoteLetters == MidiOptions.NoteNameLetter) { return(Letter(notenumber, whitenote)); } else if (sheetmusic.ShowNoteLetters == MidiOptions.NoteNameFixedDoReMi) { string[] fixedDoReMi = { "La", "Li", "Ti", "Do", "Di", "Re", "Ri", "Mi", "Fa", "Fi", "So", "Si" }; int notescale = NoteScale.FromNumber(notenumber); return(fixedDoReMi[notescale]); } else if (sheetmusic.ShowNoteLetters == MidiOptions.NoteNameMovableDoReMi) { string[] fixedDoReMi = { "La", "Li", "Ti", "Do", "Di", "Re", "Ri", "Mi", "Fa", "Fi", "So", "Si" }; int mainscale = sheetmusic.MainKey.Notescale(); int diff = NoteScale.C - mainscale; notenumber += diff; if (notenumber < 0) { notenumber += 12; } int notescale = NoteScale.FromNumber(notenumber); return(fixedDoReMi[notescale]); } else if (sheetmusic.ShowNoteLetters == MidiOptions.NoteNameFixedNumber) { string[] num = { "10", "11", "12", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; int notescale = NoteScale.FromNumber(notenumber); return(num[notescale]); } else if (sheetmusic.ShowNoteLetters == MidiOptions.NoteNameMovableNumber) { string[] num = { "10", "11", "12", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; int mainscale = sheetmusic.MainKey.Notescale(); int diff = NoteScale.C - mainscale; notenumber += diff; if (notenumber < 0) { notenumber += 12; } int notescale = NoteScale.FromNumber(notenumber); return(num[notescale]); } else { return(""); } }
/* Draw a horizontal beam stem, connecting this stem with the Stem pair. * @param ytop The y location (in pixels) where the top of the staff starts. * @param topstaff The note at the top of the staff. */ private void DrawHorizBarStem(Graphics g, Pen pen, int ytop, WhiteNote topstaff) { pen.Width = SheetMusic.NoteHeight / 2; int xstart = 0; int xstart2 = 0; if (side == LeftSide) { xstart = SheetMusic.LineSpace / 4 + 1; } else if (side == RightSide) { xstart = SheetMusic.LineSpace / 4 + SheetMusic.NoteWidth; } if (pair.side == LeftSide) { xstart2 = SheetMusic.LineSpace / 4 + 1; } else if (pair.side == RightSide) { xstart2 = SheetMusic.LineSpace / 4 + SheetMusic.NoteWidth; } if (direction == Up) { int xend = width_to_pair + xstart2; int ystart = ytop + topstaff.Dist(end) * SheetMusic.NoteHeight / 2; int yend = ytop + topstaff.Dist(pair.end) * SheetMusic.NoteHeight / 2; if (duration == NoteDuration.Eighth || duration == NoteDuration.DottedEighth || duration == NoteDuration.Triplet || duration == NoteDuration.Sixteenth || duration == NoteDuration.ThirtySecond) { g.DrawLine(pen, xstart, ystart, xend, yend); } ystart += SheetMusic.NoteHeight; yend += SheetMusic.NoteHeight; /* A dotted eighth will connect to a 16th note. */ if (duration == NoteDuration.DottedEighth) { int x = xend - SheetMusic.NoteHeight; double slope = (yend - ystart) * 1.0 / (xend - xstart); int y = (int)(slope * (x - xend) + yend); g.DrawLine(pen, x, y, xend, yend); } if (duration == NoteDuration.Sixteenth || duration == NoteDuration.ThirtySecond) { g.DrawLine(pen, xstart, ystart, xend, yend); } ystart += SheetMusic.NoteHeight; yend += SheetMusic.NoteHeight; if (duration == NoteDuration.ThirtySecond) { g.DrawLine(pen, xstart, ystart, xend, yend); } } else { int xend = width_to_pair + xstart2; int ystart = ytop + topstaff.Dist(end) * SheetMusic.NoteHeight / 2 + SheetMusic.NoteHeight; int yend = ytop + topstaff.Dist(pair.end) * SheetMusic.NoteHeight / 2 + SheetMusic.NoteHeight; if (duration == NoteDuration.Eighth || duration == NoteDuration.DottedEighth || duration == NoteDuration.Triplet || duration == NoteDuration.Sixteenth || duration == NoteDuration.ThirtySecond) { g.DrawLine(pen, xstart, ystart, xend, yend); } ystart -= SheetMusic.NoteHeight; yend -= SheetMusic.NoteHeight; /* A dotted eighth will connect to a 16th note. */ if (duration == NoteDuration.DottedEighth) { int x = xend - SheetMusic.NoteHeight; double slope = (yend - ystart) * 1.0 / (xend - xstart); int y = (int)(slope * (x - xend) + yend); g.DrawLine(pen, x, y, xend, yend); } if (duration == NoteDuration.Sixteenth || duration == NoteDuration.ThirtySecond) { g.DrawLine(pen, xstart, ystart, xend, yend); } ystart -= SheetMusic.NoteHeight; yend -= SheetMusic.NoteHeight; if (duration == NoteDuration.ThirtySecond) { g.DrawLine(pen, xstart, ystart, xend, yend); } } pen.Width = 1; }
LineUpStemEnds(ChordSymbol[] chords) { Stem firstStem = chords[0].Stem; Stem lastStem = chords[chords.Length - 1].Stem; Stem middleStem = chords[1].Stem; if (firstStem.Direction == Stem.Up) { /* Find the highest stem. The beam will either: * - Slant downwards (first stem is highest) * - Slant upwards (last stem is highest) * - Be straight (middle stem is highest) */ WhiteNote top = firstStem.End; foreach (ChordSymbol chord in chords) { top = WhiteNote.Max(top, chord.Stem.End); } if (top == firstStem.End && top.Dist(lastStem.End) >= 2) { firstStem.End = top; middleStem.End = top.Add(-1); lastStem.End = top.Add(-2); } else if (top == lastStem.End && top.Dist(firstStem.End) >= 2) { firstStem.End = top.Add(-2); middleStem.End = top.Add(-1); lastStem.End = top; } else { firstStem.End = top; middleStem.End = top; lastStem.End = top; } } else { /* Find the bottommost stem. The beam will either: * - Slant upwards (first stem is lowest) * - Slant downwards (last stem is lowest) * - Be straight (middle stem is highest) */ WhiteNote bottom = firstStem.End; foreach (ChordSymbol chord in chords) { bottom = WhiteNote.Min(bottom, chord.Stem.End); } if (bottom == firstStem.End && lastStem.End.Dist(bottom) >= 2) { middleStem.End = bottom.Add(1); lastStem.End = bottom.Add(2); } else if (bottom == lastStem.End && firstStem.End.Dist(bottom) >= 2) { middleStem.End = bottom.Add(1); firstStem.End = bottom.Add(2); } else { firstStem.End = bottom; middleStem.End = bottom; lastStem.End = bottom; } } /* All middle stems have the same end */ for (int i = 1; i < chords.Length - 1; i++) { Stem stem = chords[i].Stem; stem.End = middleStem.End; } }