Example #1
0
        /// <summary>
        /// If a small ClefSymbol has no following chord in the voice, it is moved before the final barline.
        /// </summary>
        private void MoveRestClefChangesToEndOfVoice(Voice voice)
        {
            bool       restFound      = false;
            ClefSymbol smallClef      = null;
            int        smallClefIndex = -1;

            for (int i = voice.NoteObjects.Count - 1; i >= 0; --i)
            {
                if (voice.NoteObjects[i] is OutputChordSymbol)
                {
                    break;
                }
                if (voice.NoteObjects[i] is RestSymbol)
                {
                    restFound = true;
                }
                ClefSymbol clef = voice.NoteObjects[i] as ClefSymbol;
                if (clef != null && clef.FontHeight == _pageFormat.CautionaryNoteheadsFontHeight)
                {
                    smallClef      = clef;
                    smallClefIndex = i;
                    break;
                }
            }
            if (restFound && (smallClef != null))
            {
                voice.NoteObjects.RemoveAt(smallClefIndex);
                Debug.Assert(voice.NoteObjects[voice.NoteObjects.Count - 1] is Barline);
                voice.NoteObjects.Insert(voice.NoteObjects.Count - 1, smallClef);
            }
        }
Example #2
0
        /// <summary>
        /// Aligns barline glyphs in this moment, moving an immediately preceding clef, but
        /// without moving the following duration symbol (which is aligned at this.AlignmentX).
        /// </summary>
        public void AlignBarlineGlyphs()
        {
            float minBarlineOriginX = float.MaxValue;

            foreach (NoteObject noteObject in _noteObjects)
            {
                Barline b = noteObject as Barline;
                if (b != null && b.Metrics != null && b.Metrics.OriginX < minBarlineOriginX)
                {
                    minBarlineOriginX = b.Metrics.OriginX;
                }
            }
            for (int index = 0; index < _noteObjects.Count; index++)
            {
                Barline barline = _noteObjects[index] as Barline;
                if (barline != null && barline.Metrics != null)
                {
                    Debug.Assert(AlignmentX == 0F);
                    if (index > 0)
                    {
                        ClefSymbol clef = _noteObjects[index - 1] as ClefSymbol;
                        if (clef != null)
                        {
                            clef.Metrics.Move(minBarlineOriginX - barline.Metrics.OriginX, 0);
                        }
                    }
                    barline.Metrics.Move(minBarlineOriginX - barline.Metrics.OriginX, 0);
                }
            }
        }
Example #3
0
        public VerticalDir DefaultStemDirection(ClefSymbol clef)
        {
            Debug.Assert(this.HeadsTopDown.Count > 0);
            float        gap = 32F; // dummy value
            List <float> topDownHeadOriginYs = new List <float>();
            int          lastMidiPitch       = int.MaxValue;

            foreach (Head head in this.HeadsTopDown)
            {
                Debug.Assert(head.MidiPitch < lastMidiPitch);
                topDownHeadOriginYs.Add(head.GetOriginY(clef, gap));
            }

            float heightOfMiddleStaffLine = (this.Voice.Staff.NumberOfStafflines / 2) * gap;
            float halfHeight = 0F;

            if (topDownHeadOriginYs.Count == 1)
            {
                halfHeight = topDownHeadOriginYs[0];
            }
            else
            {
                halfHeight = (topDownHeadOriginYs[topDownHeadOriginYs.Count - 1] + topDownHeadOriginYs[0]) / 2;
            }

            if (halfHeight <= heightOfMiddleStaffLine)
            {
                return(VerticalDir.down);
            }
            else
            {
                return(VerticalDir.up);
            }
        }
Example #4
0
        private VerticalDir GetDirectionFromExtremes(ClefSymbol currentClef, List <ChordSymbol> chordsBeamedTogether)
        {
            float headMinTop         = float.MaxValue;
            float headMaxBottom      = float.MinValue;
            float gap                = chordsBeamedTogether[0].Voice.Staff.Gap;
            int   numberOfStafflines = chordsBeamedTogether[0].Voice.Staff.NumberOfStafflines;

            foreach (ChordSymbol chord in chordsBeamedTogether)
            {
                foreach (Head head in chord.HeadsTopDown)
                {
                    float headY = head.GetOriginY(currentClef, gap);
                    headMinTop    = headMinTop < headY ? headMinTop : headY;
                    headMaxBottom = headMaxBottom > headY ? headMaxBottom : headY;
                }
            }
            headMaxBottom -= (gap * (numberOfStafflines - 1));
            headMinTop    *= -1;
            if (headMaxBottom > headMinTop)
            {
                return(VerticalDir.up);
            }
            else
            {
                return(VerticalDir.down);
            }
        }
Example #5
0
        private float GetDefaultStemTipY(ClefSymbol currentClef, List <ChordSymbol> chordsBeamedTogether)
        {
            float       headMinTop         = float.MaxValue;
            float       headMaxBottom      = float.MinValue;
            float       gap                = chordsBeamedTogether[0].Voice.Staff.Gap;
            int         numberOfStafflines = chordsBeamedTogether[0].Voice.Staff.NumberOfStafflines;
            VerticalDir direction          = chordsBeamedTogether[0].Stem.Direction;

            foreach (ChordSymbol chord in chordsBeamedTogether)
            {
                foreach (Head head in chord.HeadsTopDown)
                {
                    float headY = head.GetOriginY(currentClef, gap);
                    headMinTop    = headMinTop < headY ? headMinTop : headY;
                    headMaxBottom = headMaxBottom > headY ? headMaxBottom : headY;
                }
            }

            if (direction == VerticalDir.up)
            {
                return(headMinTop - (gap * numberOfStafflines));
            }
            else
            {
                return(headMaxBottom + (gap * numberOfStafflines));
            }
        }
Example #6
0
        private List <ClefSymbol> GetClefs(Voice voice)
        {
            List <ClefSymbol> clefs = new List <ClefSymbol>();

            foreach (NoteObject noteObject in voice.NoteObjects)
            {
                ClefSymbol clef = noteObject as ClefSymbol;
                if (clef != null)
                {
                    clefs.Add(clef);
                }
            }
            return(clefs);
        }
Example #7
0
        private string FindClefTypeAtEndOfStaff1(Voice staff1voice0)
        {
            ClefSymbol mainStaff1Clef = staff1voice0.NoteObjects[0] as ClefSymbol;

            Debug.Assert(mainStaff1Clef != null);

            string clefTypeAtEndOfStaff1 = mainStaff1Clef.ClefType;

            foreach (NoteObject noteObject in staff1voice0.NoteObjects)
            {
                ClefChangeSymbol ccs = noteObject as ClefChangeSymbol;
                if (ccs != null)
                {
                    clefTypeAtEndOfStaff1 = ccs.ClefType;
                }
            }
            return(clefTypeAtEndOfStaff1);
        }
Example #8
0
        /// <summary>
        /// Copies Systems[systemIndex]'s content to the end of the previous system (taking account of clefs),
        /// then removes Systems[systemIndex] from the Systems list.
        /// </summary>
        /// <param name="barlineIndex"></param>
        private void JoinToPreviousSystem(int systemIndex)
        {
            Debug.Assert(Systems.Count > 1 && Systems.Count > systemIndex);
            SvgSystem system1 = Systems[systemIndex - 1];
            SvgSystem system2 = Systems[systemIndex];

            Debug.Assert(system1.Staves.Count == system2.Staves.Count);

            for (int staffIndex = 0; staffIndex < system2.Staves.Count; staffIndex++)
            {
                bool   visibleStaff          = !(system1.Staves[staffIndex] is InvisibleOutputStaff);
                string clefTypeAtEndOfStaff1 = null;
                if (visibleStaff)
                {
                    // If a staff has two voices, both contain the same clefTypes (some clefs may be invisible).
                    clefTypeAtEndOfStaff1 = FindClefTypeAtEndOfStaff1(system1.Staves[staffIndex].Voices[0]);
                }

                for (int voiceIndex = 0; voiceIndex < system2.Staves[staffIndex].Voices.Count; voiceIndex++)
                {
                    Voice voice1 = system1.Staves[staffIndex].Voices[voiceIndex];
                    Voice voice2 = system2.Staves[staffIndex].Voices[voiceIndex];
                    if (visibleStaff)
                    {
                        ClefSymbol voice2FirstClef = voice2.NoteObjects[0] as ClefSymbol;
                        Debug.Assert(voice2FirstClef != null && clefTypeAtEndOfStaff1 == voice2FirstClef.ClefType);
                        voice2.NoteObjects.Remove(voice2FirstClef);
                    }

                    try
                    {
                        voice1.AppendNoteObjects(voice2.NoteObjects);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
            }
            Systems.Remove(system2);
            system2 = null;
        }
Example #9
0
        public BeamBlock(ClefSymbol clef, List<ChordSymbol> chordsBeamedTogether, VerticalDir voiceStemDirection, float beamThickness, float strokeThickness)
            : base(null, 0, 0)
        {
            Chords = new List<ChordSymbol>(chordsBeamedTogether);
            SetBeamedGroupStemDirection(clef, chordsBeamedTogether, voiceStemDirection);
            foreach(ChordSymbol chord in chordsBeamedTogether)
                chord.BeamBlock = this; // prevents an isolated flag from being created

            _gap = Chords[0].Voice.Staff.Gap;
            _beamSeparation = _gap;
            _beamThickness = beamThickness;
            _strokeThickness = strokeThickness;
            _stemDirection = Chords[0].Stem.Direction;

            /******************************************************************************
             * Important to set stem tips to this value before justifying horizontally.
             * Allows collisions between the objects outside the tips (e.g. dynamics or ornaments)
             * to be detected correctly. */
            _defaultStemTipY = GetDefaultStemTipY(clef, chordsBeamedTogether);
        }
Example #10
0
        public BeamBlock(ClefSymbol clef, List <ChordSymbol> chordsBeamedTogether, VerticalDir voiceStemDirection, float beamThickness, float strokeThickness)
            : base(null, 0, 0)
        {
            Chords = new List <ChordSymbol>(chordsBeamedTogether);
            SetBeamedGroupStemDirection(clef, chordsBeamedTogether, voiceStemDirection);
            foreach (ChordSymbol chord in chordsBeamedTogether)
            {
                chord.BeamBlock = this; // prevents an isolated flag from being created
            }
            _gap             = Chords[0].Voice.Staff.Gap;
            _beamSeparation  = _gap;
            _beamThickness   = beamThickness;
            _strokeThickness = strokeThickness;
            _stemDirection   = Chords[0].Stem.Direction;

            /******************************************************************************
             * Important to set stem tips to this value before justifying horizontally.
             * Allows collisions between the objects outside the tips (e.g. dynamics or ornaments)
             * to be detected correctly. */
            _defaultStemTipY = GetDefaultStemTipY(clef, chordsBeamedTogether);
        }
Example #11
0
        /// <summary>
        /// This algorithm follows Gardner Read when the stemDirection is "none" (i.e. not forced):
        /// If there were no beam, and the majority of the stems would go up, then all the stems in the beam go up.
        /// ji: if there are the same number of default up and default down stems, then the direction is decided by
        /// the most extreme notehead in the beam group. If both extremes are the same (e.g. 1 ledgeline up and down)
        /// then the stems are all down.
        /// </summary>
        /// <param name="currentClef"></param>
        /// <param name="chordsBeamedTogether"></param>
        private void SetBeamedGroupStemDirection(ClefSymbol currentClef, List <ChordSymbol> chordsBeamedTogether, VerticalDir voiceStemDirection)
        {
            Debug.Assert(chordsBeamedTogether.Count > 1);
            VerticalDir groupStemDirection = voiceStemDirection;

            if (voiceStemDirection == VerticalDir.none)
            {   // here, there is only one voice in the staff, so the direction depends on the height of the noteheads.
                int upStems   = 0;
                int downStems = 0;
                foreach (ChordSymbol chord in chordsBeamedTogether)
                {
                    VerticalDir direction = chord.DefaultStemDirection(currentClef);
                    if (direction == VerticalDir.up)
                    {
                        upStems++;
                    }
                    else
                    {
                        downStems++;
                    }
                }

                if (upStems == downStems)
                {
                    groupStemDirection = GetDirectionFromExtremes(currentClef, chordsBeamedTogether);
                }
                else if (upStems > downStems)
                {
                    groupStemDirection = VerticalDir.up;
                }
                else
                {
                    groupStemDirection = VerticalDir.down;
                }
            }
            foreach (ChordSymbol chord in chordsBeamedTogether)
            {
                chord.Stem.Direction = groupStemDirection;
            }
        }
Example #12
0
        /// <summary>
        /// Adds all the staff's metrics, except for the top or bottom staffline.
        /// </summary>
        /// <param name="staff"></param>
        protected void AddStaffMetrics(Staff staff)
        {
            foreach (Voice voice in staff.Voices)
            {
                foreach (NoteObject noteObject in voice.NoteObjects)
                {
                    OutputChordSymbol chordSymbol = noteObject as OutputChordSymbol;
                    ClefSymbol        clef        = noteObject as ClefSymbol;

                    if (chordSymbol != null)
                    {
                        chordSymbol.ChordMetrics.AddToEdge(this);
                    }
                    else if (clef != null && clef.ClefType != "n")
                    {
                        Add(clef.Metrics);
                    }
                    else
                    {
                        Add(noteObject.Metrics);
                    }

                    Barline barline = noteObject as Barline;
                    if (barline != null)
                    {
                        BarlineMetrics barlineMetrics = barline.Metrics as BarlineMetrics;
                        if (barlineMetrics.BarnumberMetrics != null)
                        {
                            Add(barlineMetrics.BarnumberMetrics);
                        }
                        if (barlineMetrics.StaffNameMetrics != null)
                        {
                            Add(barlineMetrics.StaffNameMetrics);
                        }
                    }
                }
            }
        }
Example #13
0
        public override Metrics NoteObjectMetrics(Graphics graphics, NoteObject noteObject, VerticalDir voiceStemDirection, float gap, float strokeWidth)
        {
            Metrics               returnMetrics         = null;
            ClefSymbol            clef                  = noteObject as ClefSymbol;
            Barline               barline               = noteObject as Barline;
            CautionaryChordSymbol cautionaryChordSymbol = noteObject as CautionaryChordSymbol;
            ChordSymbol           chord                 = noteObject as ChordSymbol;
            RestSymbol            rest                  = noteObject as RestSymbol;

            if (barline != null)
            {
                returnMetrics = new BarlineMetrics(graphics, barline, gap);
            }
            else if (clef != null)
            {
                if (clef.ClefType != "n")
                {
                    returnMetrics = new ClefMetrics(clef, gap);
                }
            }
            else if (cautionaryChordSymbol != null)
            {
                returnMetrics = new ChordMetrics(graphics, cautionaryChordSymbol, voiceStemDirection, gap, strokeWidth);
            }
            else if (chord != null)
            {
                returnMetrics = new ChordMetrics(graphics, chord, voiceStemDirection, gap, strokeWidth);
            }
            else if (rest != null)
            {
                // All rests are originally created on the centre line.
                // They are moved vertically later, if they are on a 2-Voice staff.
                returnMetrics = new RestMetrics(graphics, rest, gap, noteObject.Voice.Staff.NumberOfStafflines, strokeWidth);
            }

            return(returnMetrics);
        }
Example #14
0
        /// <summary>
        /// Returns the head's y-coordinates wrt the chord.
        /// The chord's y-origin is the top line of the staff.
        /// (Y-Alignment of a notehead on the top line of the staff is 0.)
        /// Uses the following protected variables (in Metrics) which have been set by GetStaffParameters()
        ///     protected float _gapVBPX = 0F;
        ///     protected int _nStafflines = 0;
        ///     protected ClefSymbol _clef = null;
        /// </summary>
        /// <param name="headIndex"></param>
        /// <param name="?"></param>
        /// <param name="?"></param>
        public float GetOriginY(ClefSymbol clef, float gap)
        {
            string[] alphabet    = { "C", "D", "E", "F", "G", "A", "B" };
            float    shiftFactor = 0F;

            switch (this.Pitch[0])
            {
            case 'A':
                shiftFactor = 2.5F;
                break;

            case 'B':
                shiftFactor = 2F;
                break;

            case 'C':
                shiftFactor = 5;
                break;

            case 'D':
                shiftFactor = 4.5F;
                break;

            case 'E':
                shiftFactor = 4F;
                break;

            case 'F':
                shiftFactor = 3.5F;
                break;

            case 'G':
                shiftFactor = 3F;
                break;
            }

            // shiftFactor is currently for the octave above middle C (octave = 5) on a normal treble clef
            // F6 is at shiftFactor 0 (the top line of the staff).
            int octave = 0;

            try
            {
                string octaveString = this.Pitch.Substring(1);
                if (octaveString == ":")
                {
                    octave = 10;
                }
                else
                {
                    octave = int.Parse(octaveString);
                }
            }
            catch
            {
                Debug.Assert(false, "Error in octave string");
            }
            float octaveShift = octave - 5F;

            shiftFactor -= (octaveShift * 3.5F); // 3.5 spaces is one octave
            // shiftFactor is currently correct for all octaves on a normal treble clef
            switch (clef.ClefType)
            {
            case "t":
                break;

            case "t1":               // trebleClef8
                shiftFactor += 3.5F; // shift down one octave
                break;

            case "t2":             // trebleClef2x8
                shiftFactor += 7F; // shift down two octaves
                break;

            case "t3":                // trebleClef3x8
                shiftFactor += 10.5F; // shift down three octaves
                break;

            case "b":
                shiftFactor -= 6F;     // shift up six spaces
                break;

            case "b1":               // bassClef8
                shiftFactor -= 9.5F; // shift up six spaces + 1 octave
                break;

            case "b2":              // bassClef2x8
                shiftFactor -= 13F; // shift up six spaces + 2 octaves
                break;

            case "b3":                // bassClef3x8
                shiftFactor -= 16.5F; // shift up six spaces + 3 octaves
                break;

            default:
                break;
            }

            float headY = shiftFactor * gap;

            return(headY);
        }
Example #15
0
        public ClefMetrics(ClefSymbol clef, float gap)
            : base()
        {
            float trebleTop     = -4.35F * gap;
            float trebleRight   = 3.1F * gap;
            float highTrebleTop = -5.9F * gap;
            float trebleBottom  = 2.7F * gap;

            #region treble clefs
            switch (clef.ClefType)
            {
            case "t":
                _objectType = "trebleClef";
                _top        = trebleTop;
                _right      = trebleRight;
                _bottom     = trebleBottom;
                break;

            case "t1":                     // trebleClef8
                _objectType = "trebleClef8";
                _top        = highTrebleTop;
                _right      = trebleRight;
                _bottom     = trebleBottom;
                break;

            case "t2":                     // trebleClef2x8
                _objectType = "trebleClef2x8";
                _top        = highTrebleTop;
                _right      = trebleRight;
                _bottom     = trebleBottom;
                break;

            case "t3":                     // trebleClef3x8
                _objectType = "trebleClef3x8";
                _top        = highTrebleTop;
                _right      = trebleRight;
                _bottom     = trebleBottom;
                break;

            default:                     // can be a bass clef ( see below)
                break;
            }

            if (_right > 0F)
            {
                Move(0F, 3 * gap);
            }
            #endregion treble clefs

            if (!(_right > 0F))
            {
                float bassTop       = -gap;
                float bassRight     = trebleRight;
                float bassBottom    = gap * 3F;
                float lowBassBottom = gap * 4.5F;
                #region bass clefs
                switch (clef.ClefType)
                {
                case "b":
                    _objectType = "bassClef";
                    _top        = bassTop;
                    _right      = bassRight;
                    _bottom     = bassBottom;
                    break;

                case "b1":                         // bassClef8
                    _objectType = "bassClef8";
                    _top        = bassTop;
                    _right      = bassRight;
                    _bottom     = lowBassBottom;
                    break;

                case "b2":                         // bassClef2x8
                    _objectType = "bassClef2x8";
                    _top        = bassTop;
                    _right      = bassRight;
                    _bottom     = lowBassBottom;
                    break;

                case "b3":                         // bassClef3x8
                    _objectType = "bassClef3x8";
                    _top        = bassTop;
                    _right      = bassRight;
                    _bottom     = lowBassBottom;
                    break;

                default:
                    Debug.Assert(false, "Unknown clef type.");
                    break;
                }
                if (_right > 0F)
                {
                    Move(0, gap);
                }
            }
            #endregion

            FontHeight = clef.FontHeight;
        }
Example #16
0
        /// <summary>
        /// This algorithm follows Gardner Read when the stemDirection is "none" (i.e. not forced):
        /// If there were no beam, and the majority of the stems would go up, then all the stems in the beam go up.
        /// ji: if there are the same number of default up and default down stems, then the direction is decided by
        /// the most extreme notehead in the beam group. If both extremes are the same (e.g. 1 ledgeline up and down)
        /// then the stems are all down.
        /// </summary>
        /// <param name="currentClef"></param>
        /// <param name="chordsBeamedTogether"></param>
        private void SetBeamedGroupStemDirection(ClefSymbol currentClef, List<ChordSymbol> chordsBeamedTogether, VerticalDir voiceStemDirection)
        {
            Debug.Assert(chordsBeamedTogether.Count > 1);
            VerticalDir groupStemDirection = voiceStemDirection;
            if(voiceStemDirection == VerticalDir.none)
            {   // here, there is only one voice in the staff, so the direction depends on the height of the noteheads.
                int upStems = 0;
                int downStems = 0;
                foreach(ChordSymbol chord in chordsBeamedTogether)
                {
                    VerticalDir direction = chord.DefaultStemDirection(currentClef);
                    if(direction == VerticalDir.up)
                        upStems++;
                    else
                        downStems++;
                }

                if(upStems == downStems)
                    groupStemDirection = GetDirectionFromExtremes(currentClef, chordsBeamedTogether);
                else if(upStems > downStems)
                    groupStemDirection = VerticalDir.up;
                else
                    groupStemDirection = VerticalDir.down;
            }
            foreach(ChordSymbol chord in chordsBeamedTogether)
            {
                chord.Stem.Direction = groupStemDirection;
            }
        }
Example #17
0
        private VerticalDir GetDirectionFromExtremes(ClefSymbol currentClef, List<ChordSymbol> chordsBeamedTogether)
        {
            float headMinTop = float.MaxValue;
            float headMaxBottom = float.MinValue;
            float gap = chordsBeamedTogether[0].Voice.Staff.Gap;
            int numberOfStafflines = chordsBeamedTogether[0].Voice.Staff.NumberOfStafflines;

            foreach(ChordSymbol chord in chordsBeamedTogether)
            {
                foreach(Head head in chord.HeadsTopDown)
                {
                    float headY = head.GetOriginY(currentClef, gap);
                    headMinTop = headMinTop < headY ? headMinTop : headY;
                    headMaxBottom = headMaxBottom > headY ? headMaxBottom : headY;
                }
            }
            headMaxBottom -= (gap * (numberOfStafflines - 1));
            headMinTop *= -1;
            if(headMaxBottom > headMinTop)
                return VerticalDir.up;
            else
                return VerticalDir.down;
        }
Example #18
0
        private float GetDefaultStemTipY(ClefSymbol currentClef, List<ChordSymbol> chordsBeamedTogether)
        {
            float headMinTop = float.MaxValue;
            float headMaxBottom = float.MinValue;
            float gap = chordsBeamedTogether[0].Voice.Staff.Gap;
            int numberOfStafflines = chordsBeamedTogether[0].Voice.Staff.NumberOfStafflines;
            VerticalDir direction = chordsBeamedTogether[0].Stem.Direction;

            foreach(ChordSymbol chord in chordsBeamedTogether)
            {
                foreach(Head head in chord.HeadsTopDown)
                {
                    float headY = head.GetOriginY(currentClef, gap);
                    headMinTop = headMinTop < headY ? headMinTop : headY;
                    headMaxBottom = headMaxBottom > headY ? headMaxBottom : headY;
                }
            }

            if(direction == VerticalDir.up)
                return headMinTop - (gap * numberOfStafflines);
            else
                return headMaxBottom + (gap * numberOfStafflines);
        }
Example #19
0
        /// <summary>
        /// Sets Chord.Stem.Direction for each chord.
        /// Chords are beamed together, duration classes permitting, unless a rest or clef intervenes.
        /// If a barline intervenes, and beamsCrossBarlines is true, the chords are beamed together.
        /// If a barline intervenes, and beamsCrossBarlines is false, the beam is broken.
        /// </summary>
        public void SetChordStemDirectionsAndCreateBeamBlocks(PageFormat pageFormat)
        {
            List <ChordSymbol> chordsBeamedTogether = new List <ChordSymbol>();
            ClefSymbol         currentClef          = null;
            bool        breakGroup = false;
            ChordSymbol lastChord  = null;

            foreach (ChordSymbol cs in ChordSymbols)
            {
                lastChord = cs;
            }

            foreach (NoteObject noteObject in NoteObjects)
            {
                CautionaryChordSymbol cautionaryChord = noteObject as CautionaryChordSymbol;
                ChordSymbol           chord           = noteObject as ChordSymbol;
                RestSymbol            rest            = noteObject as RestSymbol;
                ClefSymbol            clef            = noteObject as ClefSymbol;
                Barline barline = noteObject as Barline;

                if (cautionaryChord != null)
                {
                    continue;
                }

                if (chord != null)
                {
                    if (chord.DurationClass == DurationClass.cautionary ||
                        chord.DurationClass == DurationClass.breve ||
                        chord.DurationClass == DurationClass.semibreve ||
                        chord.DurationClass == DurationClass.minim ||
                        chord.DurationClass == DurationClass.crotchet)
                    {
                        if (currentClef != null)
                        {
                            if (this.StemDirection == VerticalDir.none)
                            {
                                chord.Stem.Direction = chord.DefaultStemDirection(currentClef);
                            }
                            else
                            {
                                chord.Stem.Direction = this.StemDirection;
                            }
                        }
                        breakGroup = true;
                    }
                    else
                    {
                        chordsBeamedTogether.Add(chord);
                        if (chord.Stem.BeamContinues) // this is true by default
                        {
                            breakGroup = false;
                        }
                        else
                        {
                            breakGroup = true;
                        }
                    }
                }

                if (chordsBeamedTogether.Count > 0)
                {
                    if (rest != null)
                    {
                        if (rest.LocalCautionaryChordDef == null)
                        {
                            breakGroup = true;
                        }
                    }

                    if (clef != null)
                    {
                        breakGroup = true;
                    }

                    if (barline != null && !pageFormat.BeamsCrossBarlines)
                    {
                        breakGroup = true;
                    }

                    if (chord == lastChord)
                    {
                        breakGroup = true;
                    }
                }

                if (chordsBeamedTogether.Count > 0 && breakGroup)
                {
                    if (currentClef != null)
                    {
                        if (chordsBeamedTogether.Count == 1)
                        {
                            if (this.StemDirection == VerticalDir.none)
                            {
                                chordsBeamedTogether[0].Stem.Direction = chordsBeamedTogether[0].DefaultStemDirection(currentClef);
                            }
                            else
                            {
                                chordsBeamedTogether[0].Stem.Direction = this.StemDirection;
                            }
                        }
                        else if (chordsBeamedTogether.Count > 1)
                        {
                            float beamThickness       = pageFormat.BeamThickness;
                            float beamStrokeThickness = pageFormat.StafflineStemStrokeWidth;
                            if (this is InputVoice)
                            {
                                beamThickness       *= pageFormat.InputStavesSizeFactor;
                                beamStrokeThickness *= pageFormat.InputStavesSizeFactor;
                            }
                            chordsBeamedTogether[0].BeamBlock =
                                new BeamBlock(currentClef, chordsBeamedTogether, this.StemDirection, beamThickness, beamStrokeThickness);
                        }
                    }
                    chordsBeamedTogether.Clear();
                }

                if (clef != null)
                {
                    currentClef = clef;
                }
            }
        }
Example #20
0
        public ClefMetrics(ClefSymbol clef, float gap)
            : base()
        {
            float trebleTop = -4.35F * gap;
            float trebleRight = 3.1F * gap;
            float highTrebleTop = -5.9F * gap;
            float trebleBottom = 2.7F * gap;
            #region treble clefs
            switch(clef.ClefType)
            {
                case "t":
                    _objectType = "trebleClef";
                    _top = trebleTop;
                    _right = trebleRight;
                    _bottom = trebleBottom;
                    break;
                case "t1": // trebleClef8
                    _objectType = "trebleClef8";
                    _top = highTrebleTop;
                    _right = trebleRight;
                    _bottom = trebleBottom;
                    break;
                case "t2": // trebleClef2x8
                    _objectType = "trebleClef2x8";
                    _top = highTrebleTop;
                    _right = trebleRight;
                    _bottom = trebleBottom;
                    break;
                case "t3": // trebleClef3x8
                    _objectType = "trebleClef3x8";
                    _top = highTrebleTop;
                    _right = trebleRight;
                    _bottom = trebleBottom;
                    break;
                default: // can be a bass clef ( see below)
                    break;
            }

            if(_right > 0F)
            {
                Move(0F, 3 * gap);
            }
            #endregion treble clefs

            if(!(_right > 0F))
            {
                float bassTop = -gap;
                float bassRight = trebleRight;
                float bassBottom = gap * 3F;
                float lowBassBottom = gap * 4.5F;
                #region bass clefs
                switch(clef.ClefType)
                {
                    case "b":
                        _objectType = "bassClef";
                        _top = bassTop;
                        _right = bassRight;
                        _bottom = bassBottom;
                        break;
                    case "b1": // bassClef8
                        _objectType = "bassClef8";
                        _top = bassTop;
                        _right = bassRight;
                        _bottom = lowBassBottom;
                        break;
                    case "b2": // bassClef2x8
                        _objectType = "bassClef2x8";
                        _top = bassTop;
                        _right = bassRight;
                        _bottom = lowBassBottom;
                        break;
                    case "b3": // bassClef3x8
                        _objectType = "bassClef3x8";
                        _top = bassTop;
                        _right = bassRight;
                        _bottom = lowBassBottom;
                        break;
                    default:
                        Debug.Assert(false, "Unknown clef type.");
                        break;
                }
                if(_right > 0F)
                {
                    Move(0, gap);
                }

            }
                #endregion

            FontHeight = clef.FontHeight;
        }
Example #21
0
        private void GetStaffParameters(NoteObject rootObject)
        {
            // If a staff has two voices, both should contain the same clefs.
            // The clefs are, however, different objects in the two voices:
            // clef.IsVisible may be true in one voice and false in the other one.

            Voice voice = rootObject.Voice;
            _staffOriginY = voice.Staff.Metrics.StafflinesTop;

            _nStafflines = voice.Staff.NumberOfStafflines;
            foreach(NoteObject noteObject in voice.NoteObjects)
            {
                ClefSymbol cs = noteObject as ClefSymbol;
                if(cs != null)
                    _clef = cs;
                if(noteObject == rootObject)
                    break;
            }
        }
Example #22
0
        /// <summary>
        /// Returns the head's y-coordinates wrt the chord.
        /// The chord's y-origin is the top line of the staff.
        /// (Y-Alignment of a notehead on the top line of the staff is 0.)
        /// Uses the following protected variables (in Metrics) which have been set by GetStaffParameters()
        ///     protected float _gapVBPX = 0F; 
        ///     protected int _nStafflines = 0;
        ///     protected ClefSymbol _clef = null;
        /// </summary>
        /// <param name="headIndex"></param>
        /// <param name="?"></param>
        /// <param name="?"></param>
        public float GetOriginY(ClefSymbol clef, float gap)
        {
            string[] alphabet = { "C", "D", "E", "F", "G", "A", "B" };
            float shiftFactor = 0F;
            switch(this.Pitch[0])
            {
                case 'A':
                    shiftFactor = 2.5F;
                    break;
                case 'B':
                    shiftFactor = 2F;
                    break;
                case 'C':
                    shiftFactor = 5;
                    break;
                case 'D':
                    shiftFactor = 4.5F;
                    break;
                case 'E':
                    shiftFactor = 4F;
                    break;
                case 'F':
                    shiftFactor = 3.5F;
                    break;
                case 'G':
                    shiftFactor = 3F;
                    break;
            }

            // shiftFactor is currently for the octave above middle C (octave = 5) on a normal treble clef
            // F6 is at shiftFactor 0 (the top line of the staff).
            int octave = 0;
            try
            {
                string octaveString = this.Pitch.Substring(1);
                if(octaveString == ":")
                    octave = 10;
                else
                    octave = int.Parse(octaveString);
            }
            catch
            {
                Debug.Assert(false, "Error in octave string");
            }
            float octaveShift = octave - 5F;
            shiftFactor -= (octaveShift * 3.5F); // 3.5 spaces is one octave
            // shiftFactor is currently correct for all octaves on a normal treble clef
            switch(clef.ClefType)
            {
                case "t":
                    break;
                case "t1": // trebleClef8
                    shiftFactor += 3.5F; // shift down one octave
                    break;
                case "t2": // trebleClef2x8
                    shiftFactor += 7F; // shift down two octaves
                    break;
                case "t3": // trebleClef3x8
                    shiftFactor += 10.5F; // shift down three octaves
                    break;
                case "b":
                    shiftFactor -= 6F; // shift up six spaces
                    break;
                case "b1": // bassClef8
                    shiftFactor -= 9.5F; // shift up six spaces + 1 octave
                    break;
                case "b2": // bassClef2x8
                    shiftFactor -= 13F; // shift up six spaces + 2 octaves
                    break;
                case "b3": // bassClef3x8
                    shiftFactor -= 16.5F; // shift up six spaces + 3 octaves
                    break;
                default:
                    break;
            }

            float headY = shiftFactor * gap;
            return headY;
        }
Example #23
0
        private void AddExtendersAtTheBeginningsofStaves(List <Staff> staves, float rightMarginPos, float gap, float extenderStrokeWidth, float hairlinePadding)
        {
            foreach (Staff staff in staves)
            {
                if (!(staff is InvisibleOutputStaff))
                {
                    foreach (Voice voice in staff.Voices)
                    {
                        List <NoteObject>     noteObjects           = voice.NoteObjects;
                        ClefSymbol            firstClef             = null;
                        CautionaryChordSymbol cautionaryChordSymbol = null;
                        ChordSymbol           firstChord            = null;
                        RestSymbol            firstRest             = null;
                        for (int index = 0; index < noteObjects.Count; ++index)
                        {
                            if (firstClef == null)
                            {
                                firstClef = noteObjects[index] as ClefSymbol;
                            }
                            if (cautionaryChordSymbol == null)
                            {
                                cautionaryChordSymbol = noteObjects[index] as CautionaryChordSymbol;
                            }
                            if (firstChord == null)
                            {
                                firstChord = noteObjects[index] as ChordSymbol;
                            }
                            if (firstRest == null)
                            {
                                firstRest = noteObjects[index] as RestSymbol;
                            }

                            if (firstClef != null &&
                                (cautionaryChordSymbol != null || firstChord != null || firstRest != null))
                            {
                                break;
                            }
                        }

                        if (firstClef != null && cautionaryChordSymbol != null)
                        {
                            // create brackets
                            List <CautionaryBracketMetrics> cbMetrics = cautionaryChordSymbol.ChordMetrics.CautionaryBracketsMetrics;
                            Debug.Assert(cbMetrics.Count == 2);
                            Metrics clefMetrics = firstClef.Metrics;

                            // extender left of cautionary
                            List <float> ys  = cautionaryChordSymbol.ChordMetrics.HeadsOriginYs;
                            List <float> x1s = GetEqualFloats(clefMetrics.Right - (hairlinePadding * 2), ys.Count);
                            List <float> x2s = GetEqualFloats(cbMetrics[0].Left, ys.Count);
                            for (int i = 0; i < x2s.Count; ++i)
                            {
                                if ((x2s[i] - x1s[i]) < gap)
                                {
                                    x1s[i] = x2s[i] - gap;
                                }
                            }
                            cautionaryChordSymbol.ChordMetrics.NoteheadExtendersMetricsBefore =
                                CreateExtenders(x1s, x2s, ys, extenderStrokeWidth, gap, true);

                            // extender right of cautionary
                            x1s = GetEqualFloats(cbMetrics[1].Right, ys.Count);
                            x2s = GetCautionaryRightExtenderX2s(cautionaryChordSymbol, voice.NoteObjects, x1s, ys, hairlinePadding);
                            cautionaryChordSymbol.ChordMetrics.NoteheadExtendersMetrics =
                                CreateExtenders(x1s, x2s, ys, extenderStrokeWidth, gap, true);
                        }
                    }
                }
            }
        }
Example #24
0
        public VerticalDir DefaultStemDirection(ClefSymbol clef)
        {
            Debug.Assert(this.HeadsTopDown.Count > 0);
            float gap = 32F; // dummy value
            List<float> topDownHeadOriginYs = new List<float>();
            int lastMidiPitch = int.MaxValue;
            foreach(Head head in this.HeadsTopDown)
            {
                Debug.Assert(head.MidiPitch < lastMidiPitch);
                topDownHeadOriginYs.Add(head.GetOriginY(clef, gap));
            }

            float heightOfMiddleStaffLine = (this.Voice.Staff.NumberOfStafflines / 2) * gap;
            float halfHeight = 0F;
            if(topDownHeadOriginYs.Count == 1)
                halfHeight = topDownHeadOriginYs[0];
            else
                halfHeight = (topDownHeadOriginYs[topDownHeadOriginYs.Count - 1] + topDownHeadOriginYs[0]) / 2;

            if(halfHeight <= heightOfMiddleStaffLine)
                return VerticalDir.down;
            else
                return VerticalDir.up;
        }