import Vex from "vexflow" ; import { Staff } from "../../VoiceData/Staff" ; import { SourceMeasure } from "../../VoiceData/SourceMeasure" ; import { VexFlowMeasure } from "./VexFlowMeasure" ; import { VexFlowStaffEntry } from "./VexFlowStaffEntry" ; import { VexFlowConverter } from "./VexFlowConverter" ; import { StaffLine } from "../StaffLine" ; import { GraphicalVoiceEntry } from "../GraphicalVoiceEntry" ; import { VexFlowVoiceEntry } from "./VexFlowVoiceEntry" ; import { Arpeggio } from "../../VoiceData/Arpeggio" ; import { Voice } from "../../VoiceData/Voice" ; import log from "loglevel" ; export class VexFlowTabMeasure extends VexFlowMeasure { constructor ( staff , sourceMeasure = undefined , staffLine = undefined ) { super ( staff , sourceMeasure , staffLine ) ; this . isTabMeasure = true ; } /**
     * Reset all the geometric values and parameters of this measure and put it in an initialized state.
     * This is needed to evaluate a measure a second time by system builder.
     */ public resetLayout ( ) { const stafflineCount = this . ParentStaff . StafflineCount ?? 6 ; this . stave = new Vex . Flow . TabStave ( 0 , 0 , 0 , { space_above_staff_ln : 0 , space_below_staff_ln : 0 , num_lines : stafflineCount } ) ; this . updateInstructionWidth ( ) ; } public graphicalMeasureCreatedCalculations ( ) { for ( let idx = 0 , len = this . staffEntries . length ; idx < len ; ++ idx ) { const graphicalStaffEntry = ( this . staffEntries [ idx ] as VexFlowStaffEntry ) ; for ( const gve of graphicalStaffEntry . graphicalVoiceEntries ) { if ( gve . notes [ 0 ] . sourceNote . isRest ( ) ) { ( gve as VexFlowVoiceEntry ) . vfStaveNote = VexFlowConverter . GhostNotes ( gve . notes [ 0 ] . sourceNote . Length ) [ 0 ] ; } else { ( gve as VexFlowVoiceEntry ) . vfStaveNote = VexFlowConverter . CreateTabNote ( gve ) ; } } } if ( this . rules . TupletNumbersInTabs ) { this . finalizeTuplets ( ) ; } const voices = this . getVoicesWithinMeasure ( ) ; for ( const voice of voices ) { if ( ! voice ) { continue ; } this . vfVoices [ voice . VoiceId ] = new Vex . Flow . Voice ( { beat_value : this . parentSourceMeasure . Duration . Denominator , num_beats : this . parentSourceMeasure . Duration . Numerator , resolution : Vex . Flow . RESOLUTION , } ) . setMode ( Vex . Flow . Voice . Mode . SOFT ) ; const restFilledEntries = this . getRestFilledVexFlowStaveNotesPerVoice ( voice ) ; for ( const voiceEntry of restFilledEntries ) { if ( voiceEntry . parentVoiceEntry ) { if ( voiceEntry . parentVoiceEntry . IsGrace && ! voiceEntry . parentVoiceEntry . GraceAfterMainNote ) { continue ; } } const vexFlowVoiceEntry = voiceEntry as VexFlowVoiceEntry ; if ( voiceEntry . notes . length === 0 || ! voiceEntry . notes [ 0 ] || ! voiceEntry . notes [ 0 ] . sourceNote . PrintObject ) { this . vfVoices [ voice . VoiceId ] . addTickable ( vexFlowVoiceEntry . vfStaveNote ) ; continue ; } if ( voiceEntry . parentVoiceEntry && voiceEntry . parentVoiceEntry . Arpeggio ) { const arpeggio = voiceEntry . parentVoiceEntry . Arpeggio ; if ( voiceEntry . notes && voiceEntry . notes . length > 1 ) { const type = VexFlowConverter . StrokeTypeFromArpeggioType ( arpeggio . type ) ; const stroke = new Vex . Flow . Stroke ( type , { all_voices : this . rules . ArpeggiosGoAcrossVoices } ) ; if ( this . rules . RenderArpeggios ) { vexFlowVoiceEntry . vfStaveNote . addStroke ( 0 , stroke ) ; } } else { log . debug ( `[OSMD] arpeggio in measure ${ this . MeasureNumber } could not be drawn.
                        voice entry had less than two notes, arpeggio is likely between voice entries, not currently supported in Vexflow.` ) ; } } this . vfVoices [ voice . VoiceId ] . addTickable ( vexFlowVoiceEntry . vfStaveNote ) ; } } } }