private float DurationClassDeltaAbove(DurationClass durationClass, float gap) { float delta = 0F; switch (durationClass) { case DurationClass.semibreve: delta = gap / -2F; break; case DurationClass.breve: case DurationClass.minim: case DurationClass.crotchet: case DurationClass.quaver: case DurationClass.semiquaver: case DurationClass.threeFlags: break; case DurationClass.fourFlags: delta = gap / -2F; break; case DurationClass.fiveFlags: delta = gap * -1.5F; break; } return(delta); }
private double DurationClassDeltaAbove(DurationClass durationClass, double gap) { double delta = 0; switch (durationClass) { case DurationClass.semibreve: delta = gap / -2; break; case DurationClass.breve: case DurationClass.minim: case DurationClass.crotchet: case DurationClass.quaver: case DurationClass.semiquaver: case DurationClass.threeFlags: break; case DurationClass.fourFlags: delta = gap / -2; break; case DurationClass.fiveFlags: delta = gap * -1.5; break; } return(delta); }
private Beam NewBeam(DurationClass durationClass, float leftX, float rightX, bool isStub) { Beam newBeam = null; switch (durationClass) { case DurationClass.fiveFlags: if (isStub) { newBeam = new FiveFlagsBeamStub(leftX, rightX); } else { newBeam = new FiveFlagsBeam(leftX, rightX); } break; case DurationClass.fourFlags: if (isStub) { newBeam = new FourFlagsBeamStub(leftX, rightX); } else { newBeam = new FourFlagsBeam(leftX, rightX); } break; case DurationClass.threeFlags: if (isStub) { newBeam = new ThreeFlagsBeamStub(leftX, rightX); } else { newBeam = new ThreeFlagsBeam(leftX, rightX); } break; case DurationClass.semiquaver: if (isStub) { newBeam = new SemiquaverBeamStub(leftX, rightX); } else { newBeam = new SemiquaverBeam(leftX, rightX); } break; case DurationClass.quaver: newBeam = new QuaverBeam(leftX, rightX); break; default: Debug.Assert(false, "Illegal beam duration class"); break; } return(newBeam); }
private List <Beam> CreateBeams(DurationClass durationClass, float stubWidth) { List <Beam> newBeams = new List <Beam>(); bool inBeam = false; float beamLeft = -1F; float beamRight = -1F; ChordMetrics rightMostChordMetrics = (ChordMetrics)Chords[Chords.Count - 1].Metrics; float rightMostStemX = rightMostChordMetrics.StemMetrics.OriginX; int stemNumber = 1; foreach (ChordSymbol chord in Chords) { ChordMetrics chordMetrics = (ChordMetrics)chord.Metrics; float stemX = chordMetrics.StemMetrics.OriginX; bool hasLessThanOrEqualBeams = HasLessThanOrEqualBeams(durationClass, chord.DurationClass); if (!inBeam && hasLessThanOrEqualBeams) { beamLeft = stemX; beamRight = stemX; inBeam = true; } else if (inBeam && hasLessThanOrEqualBeams) { beamRight = stemX; } if (inBeam && ((!hasLessThanOrEqualBeams) || stemX == rightMostStemX)) // different durationClass or end of beamBlock { bool isStub = false; if (beamLeft == beamRight) { // Create a beamStub. All beam stubs are initially to the left of the stem to which they are attached. // Beam stubs attached to the first stem in a beamed group are replaced later in this function. beamLeft -= stubWidth; isStub = true; } Beam newBeam = NewBeam(durationClass, beamLeft, beamRight, isStub); newBeams.Add(newBeam); inBeam = false; } stemNumber++; } ChordMetrics leftMostChordMetrics = (ChordMetrics)Chords[0].Metrics; float leftMostStemX = leftMostChordMetrics.StemMetrics.OriginX; if (newBeams.Count > 0 && newBeams[0].LeftX < leftMostStemX && newBeams[0].RightX == leftMostStemX) { // Replace a beamStub on the left of the first stem by a beam stub on the right. Beam newBeam = NewBeam(durationClass, leftMostStemX, leftMostStemX + stubWidth, true); newBeams.RemoveAt(0); newBeams.Insert(0, newBeam); } return(newBeams); }
/// <summary> /// Adjusts the heights of stem tips and beamBlocks in staves which have 2 voices. /// Only adjusts stems of chords belonging to beamBlocks. /// </summary> public void AdjustStemAndBeamBlockHeights(int voiceIndex) { Debug.Assert(Voices.Count == 2); Debug.Assert(voiceIndex == 0 || voiceIndex == 1); Debug.Assert(Voices[0].StemDirection == VerticalDir.up); Debug.Assert(Voices[1].StemDirection == VerticalDir.down); int adjustVoiceIndex = 0; int otherVoiceIndex = 1; if (voiceIndex == 1) { adjustVoiceIndex = 1; otherVoiceIndex = 0; } foreach (ChordSymbol chordSymbol in Voices[adjustVoiceIndex].ChordSymbols) { DurationClass durationClass = chordSymbol.DurationClass; if (durationClass == DurationClass.quaver || durationClass == DurationClass.semiquaver || durationClass == DurationClass.threeFlags || durationClass == DurationClass.fourFlags || durationClass == DurationClass.fiveFlags) { // fix stem and beam if (chordSymbol.BeamBlock != null) { chordSymbol.BeamBlock.ShiftStemsForOtherVoice(Voices[otherVoiceIndex]); } } } }
/// <summary> /// returns true if the currentDC has a less than or equal number of beams than the stemDC /// </summary> /// <param name="currentDC"></param> /// <param name="stemDC"></param> /// <returns></returns> private bool HasLessThanOrEqualBeams(DurationClass currentDC, DurationClass stemDC) { bool hasLessThanOrEqualBeams = false; switch (currentDC) { case DurationClass.fiveFlags: if (stemDC == DurationClass.fiveFlags) { hasLessThanOrEqualBeams = true; } break; case DurationClass.fourFlags: if (stemDC == DurationClass.fiveFlags || stemDC == DurationClass.fourFlags) { hasLessThanOrEqualBeams = true; } break; case DurationClass.threeFlags: if (stemDC == DurationClass.fiveFlags || stemDC == DurationClass.fourFlags || stemDC == DurationClass.threeFlags) { hasLessThanOrEqualBeams = true; } break; case DurationClass.semiquaver: if (stemDC == DurationClass.fiveFlags || stemDC == DurationClass.fourFlags || stemDC == DurationClass.threeFlags || stemDC == DurationClass.semiquaver) { hasLessThanOrEqualBeams = true; } break; case DurationClass.quaver: if (stemDC == DurationClass.fiveFlags || stemDC == DurationClass.fourFlags || stemDC == DurationClass.threeFlags || stemDC == DurationClass.semiquaver || stemDC == DurationClass.quaver) { hasLessThanOrEqualBeams = true; } break; } return(hasLessThanOrEqualBeams); }
/// <summary> /// Used when creating temporary heads for chord alignment purposes. /// </summary> public HeadMetrics(HeadMetrics otherHead, DurationClass durationClass) : base(durationClass, false, otherHead.FontHeight) { // move to position of other head Move(otherHead.OriginX - _originX, otherHead.OriginY - OriginY); float horizontalPadding = otherHead.FontHeight * 0.04F; _leftStemX = _left; _rightStemX = _right; _left -= horizontalPadding; _right += horizontalPadding; }
/// <summary> /// Used when creating temporary heads for chord alignment purposes. /// </summary> public HeadMetrics(HeadMetrics otherHead, DurationClass durationClass) : base(durationClass, otherHead.FontHeight, CSSObjectClass.none) { // move to position of other head Move(otherHead.OriginX - _originX, otherHead.OriginY - OriginY); double horizontalPadding = otherHead.FontHeight * 0.04; _leftStemX = _left; _rightStemX = _right; _left -= horizontalPadding; _right += horizontalPadding; }
/// <summary> /// Used by RestMetrics and HeadMetrics /// </summary> public CLichtCharacterMetrics(DurationClass durationClass, double fontHeight, CSSObjectClass cssClass) : base(cssClass, "CLicht", fontHeight) { _characterString = GetClichtCharacterString(durationClass, cssClass == CSSObjectClass.rest); M.Assert(_characterString != null); Metrics m = CLichtFontMetrics.CLichtGlyphBoundingBoxesDictPX[_characterString]; _originY = 0; _top = m.Top * fontHeight; _bottom = m.Bottom * fontHeight; // move so that Left = 0. _left = 0; _right = (m.Right - m.Left) * fontHeight; _originX = -m.Left * fontHeight; _fontHeight = fontHeight; }
public CLichtCharacterMetrics(DurationClass durationClass, bool isRest, float fontHeight) : base() { _objectType = GetClichtCharacterString(durationClass, isRest); Debug.Assert(_objectType != null); Metrics m = CLichtFontMetrics.CLichtGlyphBoundingBoxesDictPX[_objectType]; _originY = 0; _top = m.Top * fontHeight; _bottom = m.Bottom * fontHeight; // move so that Left = 0. _left = 0; _right = (m.Right - m.Left) * fontHeight; _originX = -m.Left * fontHeight; _fontHeight = fontHeight; }
/// <summary> /// Rests and noteheads /// </summary> /// <param name="durationClass"></param> /// <returns></returns> private string GetClichtCharacterString(DurationClass durationClass, bool isRest) { string cLichtCharacterString = null; if (isRest) { switch (durationClass) { #region rests case DurationClass.breve: case DurationClass.semibreve: cLichtCharacterString = "∑"; break; case DurationClass.minim: cLichtCharacterString = "Ó"; break; case DurationClass.crotchet: cLichtCharacterString = "Œ"; break; case DurationClass.quaver: cLichtCharacterString = "‰"; break; case DurationClass.semiquaver: cLichtCharacterString = "≈"; break; case DurationClass.threeFlags: cLichtCharacterString = "®"; break; case DurationClass.fourFlags: cLichtCharacterString = "Ù"; break; case DurationClass.fiveFlags: cLichtCharacterString = "Â"; break; #endregion } } else { switch (durationClass) { case DurationClass.breve: cLichtCharacterString = "›"; break; case DurationClass.semibreve: cLichtCharacterString = "w"; break; case DurationClass.minim: cLichtCharacterString = "˙"; break; default: cLichtCharacterString = "œ"; break; } } return(cLichtCharacterString); }
/// <summary> /// This chord is synchronous with a chord in the other voice on the staff, or belongs to a beamBlock which /// encloses the other chord. /// If it has an outer stem tip (with or without flagsBlock) which needs to be moved outwards because it /// is too close to the noteheads in the other chord, the stem tip (and flagsBlock) is moved outwards. /// FlagsBlockMetrics exist if the duration class is small enough, and the chord is not owned by a beamBlock. /// </summary> public void AdjustStemLengthAndFlagBlock(DurationClass thisDurationClass, float thisFontHeight, List<HeadMetrics> otherHeadsMetrics) { if(_stemMetrics == null || (_stemMetrics.VerticalDir == VerticalDir.up && BottomHeadMetrics.Bottom <= otherHeadsMetrics[0].Top) || (_stemMetrics.VerticalDir == VerticalDir.down && TopHeadMetrics.Top >= otherHeadsMetrics[otherHeadsMetrics.Count -1].Bottom)) return; if(_flagsBlockMetrics != null) { FlagsBlockMetrics dummyFlagsBlockMetrics = GetFlagsBlockMetrics(otherHeadsMetrics, thisDurationClass, thisFontHeight, _stemMetrics.VerticalDir, _stemMetrics.StrokeWidth); StemMetrics dummyStemMetrics = DummyStemMetrics(otherHeadsMetrics, _stemMetrics.VerticalDir, thisFontHeight, dummyFlagsBlockMetrics, null, _stemMetrics.StrokeWidth); if(_stemMetrics.VerticalDir == VerticalDir.up) { if(dummyStemMetrics.Top < _stemMetrics.Top) { MoveOuterStemTip(dummyStemMetrics.Top, _stemMetrics.VerticalDir); _flagsBlockMetrics.Move(0F, dummyStemMetrics.Top - _flagsBlockMetrics.Top); } } else { if(dummyStemMetrics.Bottom > _stemMetrics.Bottom) { MoveOuterStemTip(dummyStemMetrics.Bottom, _stemMetrics.VerticalDir); _flagsBlockMetrics.Move(0F, dummyStemMetrics.Bottom - _flagsBlockMetrics.Bottom); } } } else // a crotchet or minim (without flagsBlock) { StemMetrics dummyStemMetrics = DummyStemMetrics(otherHeadsMetrics, _stemMetrics.VerticalDir, thisFontHeight, null, null, _stemMetrics.StrokeWidth); if(_stemMetrics.VerticalDir == VerticalDir.up) { if(dummyStemMetrics.Top < _stemMetrics.Top) { MoveOuterStemTip(dummyStemMetrics.Top + (_gap / 2F), _stemMetrics.VerticalDir); } } else { if(dummyStemMetrics.Bottom > _stemMetrics.Bottom) { MoveOuterStemTip(dummyStemMetrics.Bottom - (_gap / 2F), _stemMetrics.VerticalDir); } } } }
/// <summary> /// The duration class is DurationClass.cautionary if the duration is zero /// The duration class is DurationClass.breve if the duration is >= (minimumCrotchetDuration * 8). /// The minimumCrotchetDuration will usually be set to something like 1200ms. /// </summary> private void SetDurationClass(int msDuration, int minimumCrotchetDuration) { //_msDuration = durationMS; _minimumCrotchetDuration = minimumCrotchetDuration; if(msDuration == 0) _durationClass = DurationClass.cautionary; else if(msDuration < (_minimumCrotchetDuration / 16)) _durationClass = DurationClass.fiveFlags; else if(msDuration < (_minimumCrotchetDuration / 8)) _durationClass = DurationClass.fourFlags; else if(msDuration < (_minimumCrotchetDuration / 4)) _durationClass = DurationClass.threeFlags; else if(msDuration < (_minimumCrotchetDuration / 2)) _durationClass = DurationClass.semiquaver; else if(msDuration < _minimumCrotchetDuration) _durationClass = DurationClass.quaver; else if(msDuration < (_minimumCrotchetDuration * 2)) _durationClass = DurationClass.crotchet; else if(msDuration < (_minimumCrotchetDuration * 4)) _durationClass = DurationClass.minim; else if(msDuration < (_minimumCrotchetDuration * 8)) _durationClass = DurationClass.semibreve; else _durationClass = DurationClass.breve; }
/// <summary> /// Rests and noteheads /// </summary> /// <param name="durationClass"></param> /// <returns></returns> private string GetClichtCharacterString(DurationClass durationClass, bool isRest) { string cLichtCharacterString = null; if(isRest) { switch(durationClass) { #region rests case DurationClass.breve: case DurationClass.semibreve: cLichtCharacterString = "∑"; break; case DurationClass.minim: cLichtCharacterString = "Ó"; break; case DurationClass.crotchet: cLichtCharacterString = "Œ"; break; case DurationClass.quaver: cLichtCharacterString = "‰"; break; case DurationClass.semiquaver: cLichtCharacterString = "≈"; break; case DurationClass.threeFlags: cLichtCharacterString = "®"; break; case DurationClass.fourFlags: cLichtCharacterString = "Ù"; break; case DurationClass.fiveFlags: cLichtCharacterString = "Â"; break; #endregion } } else { switch(durationClass) { case DurationClass.breve: cLichtCharacterString = "›"; break; case DurationClass.semibreve: cLichtCharacterString = "w"; break; case DurationClass.minim: cLichtCharacterString = "˙"; break; default: cLichtCharacterString = "œ"; break; } } return cLichtCharacterString; }
/// <summary> /// Returns null if the durationClass does not have a flagsBlock, /// otherwise returns the metrics for the flagsBlock attached to this chord, correctly positioned wrt the noteheads. /// </summary> private FlagsBlockMetrics GetFlagsBlockMetrics(List<HeadMetrics> topDownHeadsMetrics, DurationClass durationClass, float fontSize, VerticalDir stemDirection, float stemThickness) { Debug.Assert(durationClass == DurationClass.quaver || durationClass == DurationClass.semiquaver || durationClass == DurationClass.threeFlags || durationClass == DurationClass.fourFlags || durationClass == DurationClass.fiveFlags); FlagsBlockMetrics flagsBlockMetrics = new FlagsBlockMetrics(durationClass, fontSize, stemDirection); if(flagsBlockMetrics != null) { // flagsMetrics contains a metrics for the flags block with the outermost point at OriginX=0, BaselineY=0 // Now move the flagblock so that is positioned correctly wrt the noteheads. SetFlagsPositionReNoteheads(topDownHeadsMetrics, flagsBlockMetrics, stemDirection, stemThickness); } return flagsBlockMetrics; }
/// <summary> /// Should be called with a duration class having a flag block /// </summary> public FlagsBlockMetrics(DurationClass durationClass, float fontHeight, VerticalDir stemDirection) : base() { _left = 0F; _right = 0.31809F * fontHeight; _originX = 0F; _originY = 0F; _fontHeight = fontHeight; _stemDirection = stemDirection; float offset = 0F; switch (durationClass) { case DurationClass.quaver: if (_stemDirection == VerticalDir.up) { _objectType = "Right1Flag"; } else { _objectType = "Left1Flag"; } break; case DurationClass.semiquaver: if (_stemDirection == VerticalDir.up) { _objectType = "Right2Flags"; } else { _objectType = "Left2Flags"; } offset = 0.25F; break; case DurationClass.threeFlags: if (_stemDirection == VerticalDir.up) { _objectType = "Right3Flags"; } else { _objectType = "Left3Flags"; } offset = 0.5F; break; case DurationClass.fourFlags: if (_stemDirection == VerticalDir.up) { _objectType = "Right4Flags"; } else { _objectType = "Left4Flags"; } offset = 0.75F; break; case DurationClass.fiveFlags: if (_stemDirection == VerticalDir.up) { _objectType = "Right5Flags"; } else { _objectType = "Left5Flags"; } offset = 1F; break; default: Debug.Assert(false, "This duration class has no flags."); break; } if (_stemDirection == VerticalDir.up) { _top = 0F; _bottom = (0.2467F + offset) * fontHeight; } else { _top = (-(0.2467F + offset)) * fontHeight; _bottom = 0F; } }
private Beam NewBeam(DurationClass durationClass, float leftX, float rightX, bool isStub) { Beam newBeam = null; switch(durationClass) { case DurationClass.fiveFlags: if(isStub) newBeam = new FiveFlagsBeamStub(leftX, rightX); else newBeam = new FiveFlagsBeam(leftX, rightX); break; case DurationClass.fourFlags: if(isStub) newBeam = new FourFlagsBeamStub(leftX, rightX); else newBeam = new FourFlagsBeam(leftX, rightX); break; case DurationClass.threeFlags: if(isStub) newBeam = new ThreeFlagsBeamStub(leftX, rightX); else newBeam = new ThreeFlagsBeam(leftX, rightX); break; case DurationClass.semiquaver: if(isStub) newBeam = new SemiquaverBeamStub(leftX, rightX); else newBeam = new SemiquaverBeam(leftX, rightX); break; case DurationClass.quaver: newBeam = new QuaverBeam(leftX, rightX); break; default: Debug.Assert(false, "Illegal beam duration class"); break; } return newBeam; }
private List<Beam> CreateBeams(DurationClass durationClass, float stubWidth) { List<Beam> newBeams = new List<Beam>(); bool inBeam = false; float beamLeft = -1F; float beamRight = -1F; ChordMetrics rightMostChordMetrics = (ChordMetrics)Chords[Chords.Count - 1].Metrics; float rightMostStemX = rightMostChordMetrics.StemMetrics.OriginX; int stemNumber = 1; foreach(ChordSymbol chord in Chords) { ChordMetrics chordMetrics = (ChordMetrics)chord.Metrics; float stemX = chordMetrics.StemMetrics.OriginX; bool hasLessThanOrEqualBeams = HasLessThanOrEqualBeams(durationClass, chord.DurationClass); if(!inBeam && hasLessThanOrEqualBeams) { beamLeft = stemX; beamRight = stemX; inBeam = true; } else if(inBeam && hasLessThanOrEqualBeams) { beamRight = stemX; } if(inBeam && ((!hasLessThanOrEqualBeams) || stemX == rightMostStemX)) // different durationClass or end of beamBlock { bool isStub = false; if(beamLeft == beamRight) { // Create a beamStub. All beam stubs are initially to the left of the stem to which they are attached. // Beam stubs attached to the first stem in a beamed group are replaced later in this function. beamLeft -= stubWidth; isStub = true; } Beam newBeam = NewBeam(durationClass, beamLeft, beamRight, isStub); newBeams.Add(newBeam); inBeam = false; } stemNumber++; } ChordMetrics leftMostChordMetrics = (ChordMetrics)Chords[0].Metrics; float leftMostStemX = leftMostChordMetrics.StemMetrics.OriginX; if(newBeams.Count > 0 && newBeams[0].LeftX < leftMostStemX && newBeams[0].RightX == leftMostStemX) { // Replace a beamStub on the left of the first stem by a beam stub on the right. Beam newBeam = NewBeam(durationClass, leftMostStemX, leftMostStemX + stubWidth, true); newBeams.RemoveAt(0); newBeams.Insert(0, newBeam); } return newBeams; }
/// <summary> /// returns true if the currentDC has a less than or equal number of beams than the stemDC /// </summary> /// <param name="currentDC"></param> /// <param name="stemDC"></param> /// <returns></returns> private bool HasLessThanOrEqualBeams(DurationClass currentDC, DurationClass stemDC) { bool hasLessThanOrEqualBeams = false; switch(currentDC) { case DurationClass.fiveFlags: if(stemDC == DurationClass.fiveFlags) hasLessThanOrEqualBeams = true; break; case DurationClass.fourFlags: if(stemDC == DurationClass.fiveFlags || stemDC == DurationClass.fourFlags) hasLessThanOrEqualBeams = true; break; case DurationClass.threeFlags: if(stemDC == DurationClass.fiveFlags || stemDC == DurationClass.fourFlags || stemDC == DurationClass.threeFlags) hasLessThanOrEqualBeams = true; break; case DurationClass.semiquaver: if(stemDC == DurationClass.fiveFlags || stemDC == DurationClass.fourFlags || stemDC == DurationClass.threeFlags || stemDC == DurationClass.semiquaver) hasLessThanOrEqualBeams = true; break; case DurationClass.quaver: if(stemDC == DurationClass.fiveFlags || stemDC == DurationClass.fourFlags || stemDC == DurationClass.threeFlags || stemDC == DurationClass.semiquaver || stemDC == DurationClass.quaver) hasLessThanOrEqualBeams = true; break; } return hasLessThanOrEqualBeams; }
/// <summary> /// Should be called with a duration class having a flag block /// </summary> public FlagsBlockMetrics(DurationClass durationClass, float fontHeight, VerticalDir stemDirection) : base() { _left = 0F; _right = 0.31809F * fontHeight; _originX = 0F; _originY = 0F; _fontHeight = fontHeight; _stemDirection = stemDirection; float offset = 0F; switch(durationClass) { case DurationClass.quaver: if(_stemDirection == VerticalDir.up) _objectType = "Right1Flag"; else _objectType = "Left1Flag"; break; case DurationClass.semiquaver: if(_stemDirection == VerticalDir.up) _objectType = "Right2Flags"; else _objectType = "Left2Flags"; offset = 0.25F; break; case DurationClass.threeFlags: if(_stemDirection == VerticalDir.up) _objectType = "Right3Flags"; else _objectType = "Left3Flags"; offset = 0.5F; break; case DurationClass.fourFlags: if(_stemDirection == VerticalDir.up) _objectType = "Right4Flags"; else _objectType = "Left4Flags"; offset = 0.75F; break; case DurationClass.fiveFlags: if(_stemDirection == VerticalDir.up) _objectType = "Right5Flags"; else _objectType = "Left5Flags"; offset = 1F; break; default: Debug.Assert(false, "This duration class has no flags."); break; } if(_stemDirection == VerticalDir.up) { _top = 0F; _bottom = (0.2467F + offset) * fontHeight; } else { _top = (-(0.2467F + offset)) * fontHeight; _bottom = 0F; } }
/// <summary> /// Should be called with a duration class having a flag block /// </summary> public FlagsMetrics(DurationClass durationClass, double fontHeight, VerticalDir stemDirection) : base(CSSObjectClass.flag) { _left = 0; // (0.31809F * fontHeight) is maximum x in the flag def. _right = (0.31809F * fontHeight); if (stemDirection == VerticalDir.up) { double rightPadding = (0.06F * fontHeight); _right += rightPadding; } _originX = 0; _originY = 0; double offset = 0; switch (durationClass) { // Bravura says there is a maximum of 8 flags case DurationClass.quaver: if (stemDirection == VerticalDir.up) { _flagID = FlagID.right1Flag; } else { _flagID = FlagID.left1Flag; } break; case DurationClass.semiquaver: if (stemDirection == VerticalDir.up) { _flagID = FlagID.right2Flags; } else { _flagID = FlagID.left2Flags; } offset = 0.25; break; case DurationClass.threeFlags: if (stemDirection == VerticalDir.up) { _flagID = FlagID.right3Flags; } else { _flagID = FlagID.left3Flags; } offset = 0.5; break; case DurationClass.fourFlags: if (stemDirection == VerticalDir.up) { _flagID = FlagID.right4Flags; } else { _flagID = FlagID.left4Flags; } offset = 0.75; break; case DurationClass.fiveFlags: if (stemDirection == VerticalDir.up) { _flagID = FlagID.right5Flags; } else { _flagID = FlagID.left5Flags; } offset = 1; break; case DurationClass.sixFlags: if (stemDirection == VerticalDir.up) { _flagID = FlagID.right6Flags; } else { _flagID = FlagID.left6Flags; } offset = 1.25; break; case DurationClass.sevenFlags: if (stemDirection == VerticalDir.up) { _flagID = FlagID.right7Flags; } else { _flagID = FlagID.left7Flags; } offset = 1.5; break; case DurationClass.eightFlags: if (stemDirection == VerticalDir.up) { _flagID = FlagID.right8Flags; } else { _flagID = FlagID.left8Flags; } offset = 1.75; break; default: M.Assert(false, "This duration class has no flags."); break; } if (stemDirection == VerticalDir.up) { _top = 0; _bottom = (0.2467F + offset) * fontHeight; } else { _top = (-(0.2467F + offset)) * fontHeight; _bottom = 0; } if (!_usedFlagIDs.Contains((FlagID)_flagID)) { _usedFlagIDs.Add((FlagID)_flagID); } }
private List<Beam> CreateBeams(DurationClass durationClass) { List<Beam> newBeams = new List<Beam>(); bool inBeam = false; float beamLeft = -1F; float beamRight = -1F; ChordMetrics rightMostChordMetrics = (ChordMetrics)Chords[Chords.Count - 1].Metrics; float rightMostStemX = rightMostChordMetrics.StemMetrics.OriginX; int stemNumber = 1; foreach(ChordSymbol chord in Chords) { ChordMetrics chordMetrics = (ChordMetrics)chord.Metrics; float stemX = chordMetrics.StemMetrics.OriginX; bool hasLessThanOrEqualBeams = HasLessThanOrEqualBeams(durationClass, chord.DurationClass); if(!inBeam && hasLessThanOrEqualBeams) { beamLeft = stemX; beamRight = stemX; inBeam = true; } else if(inBeam && hasLessThanOrEqualBeams) { beamRight = stemX; } if(inBeam && ((!hasLessThanOrEqualBeams) || stemX == rightMostStemX)) // different durationClass or end of beamBlock { // BeamStubs are initially created with LeftX == RightX == stemX. // They are replaced by proper beamStubs when the BeamBlock is complete // (See SetBeamStubs() above.) bool isStub = (beamLeft == beamRight) ? true : false; Beam newBeam = NewBeam(durationClass, beamLeft, beamRight, isStub); newBeams.Add(newBeam); inBeam = false; } stemNumber++; } return newBeams; }