예제 #1
0
        /// <summary>
        /// noteObjects[noteObjectIndex] is the first OutputChordSymbol or OutputRestSymbol in the tuplet, and is the
        /// noteObject to which the tuplet is attached,
        /// </summary>
        /// <param name="graphics"></param>
        /// <param name="tupletDef"></param>
        /// <param name="noteObjects"></param>
        /// <param name="noteObjectIndex"></param>
        public Tuplet(Graphics graphics, TupletDef tupletDef, List <NoteObject> noteObjects, int noteObjectIndex)
            : base(noteObjects[noteObjectIndex])
        {
            List <NoteObject> tupletChordsAndRests = GetTupletChordsAndRests(noteObjects, noteObjectIndex, tupletDef);

            var gap      = M.PageFormat.GapVBPX;
            var textInfo = GetTupletTextInfo(tupletDef.InnerDuration, tupletDef.OuterDuration);

            Metrics = new TextMetrics(CSSObjectClass.tupletText, graphics, textInfo);

            var    textHeight = (Metrics.Bottom - Metrics.Top);
            var    textWidth  = (Metrics.Right - Metrics.Left);
            bool   isOver     = (tupletDef.Orient == Orientation.up);
            double textXAlignment;

            if (tupletChordsAndRests.Count > 2)
            {
                int     alignedIndex = (int)(tupletChordsAndRests.Count) / 2;
                Metrics metrics      = tupletChordsAndRests[alignedIndex].Metrics;
                if (metrics is ChordMetrics cMetrics)
                {
                    textXAlignment = cMetrics.OriginX - textWidth / 4;
                }
                else
                {
                    textXAlignment = ((metrics.Right - metrics.Left) / 2) + metrics.Left;
                }
            }
            else
            {
                M.Assert(tupletChordsAndRests.Count == 2);
                Metrics metrics1 = tupletChordsAndRests[0].Metrics;
                Metrics metrics2 = tupletChordsAndRests[1].Metrics;

                textXAlignment = ((metrics1.Left + metrics2.Right) / 2) - textWidth / 4;
            }

            //textYAlignment = (isOver) ? metrics.Top - gap - (textHeight / 2) : metrics.Bottom + gap + (textHeight / 2);
            double textYAlignment = (isOver) ? double.MaxValue : double.MinValue;;

            foreach (NoteObject noteObject in tupletChordsAndRests)
            {
                var metrics = noteObject.Metrics;
                if (isOver)
                {
                    textYAlignment = (metrics.Top < textYAlignment) ? metrics.Top : textYAlignment;
                }
                else
                {
                    textYAlignment = (metrics.Bottom > textYAlignment) ? metrics.Bottom : textYAlignment;
                }
            }

            #region move vertically off the staff if necessary
            StaffMetrics staffMetrics = tupletChordsAndRests[0].Voice.Staff.Metrics;
            if (isOver)
            {
                double topMax = staffMetrics.StafflinesTop - gap - (textHeight / 2);
                if (textYAlignment > topMax)
                {
                    textYAlignment = topMax;
                }
            }
            else
            {
                double topMin = staffMetrics.StafflinesBottom + gap + (textHeight / 2);
                if (textYAlignment < topMin)
                {
                    textYAlignment = topMin;
                }
            }
            #endregion

            Metrics.Move(textXAlignment, textYAlignment + (textHeight / 2));

            // set auto correctly later -- depends on beaming
            if (tupletDef.Bracket == TupletBracketDisplay.yes || tupletDef.Bracket == TupletBracketDisplay.auto)
            {
                double bracketHoriz  = textYAlignment;
                double bracketLeft   = tupletChordsAndRests[0].Metrics.Left - M.PageFormat.StafflineStemStrokeWidthVBPX;
                double bracketRight  = tupletChordsAndRests[tupletChordsAndRests.Count - 1].Metrics.Right + M.PageFormat.StafflineStemStrokeWidthVBPX;
                double bracketHeight = gap * 0.75;

                _textAndBracketMetrics = new TupletMetrics((TextMetrics)Metrics, bracketHoriz, bracketLeft, bracketRight, bracketHeight, isOver);
            }
        }
예제 #2
0
        private List <NoteObject> GetTupletChordsAndRests(List <NoteObject> noteObjects, int noteObjectIndex, TupletDef tupletDef)
        {
            List <NoteObject> chordsAndRests = new List <NoteObject>();
            int nEvents = tupletDef.IEventsAndGraces.FindAll(e => e is Event).Count; // TODO: Tuplets can now nest and include Grace notes

            for (int i = noteObjectIndex; i < noteObjects.Count; ++i)
            {
                if (noteObjects[i] is OutputChordSymbol || noteObjects[i] is OutputRestSymbol)
                {
                    chordsAndRests.Add(noteObjects[i]);
                    if (chordsAndRests.Count == nEvents)
                    {
                        break;
                    }
                }
            }

            return(chordsAndRests);
        }