UNPKG

jianpurender

Version:

Render music score using SVG on browsers.

1 lines 27.1 kB
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.jianpu_svg_render=e():t.jianpu_svg_render=e()}(self,(()=>(()=>{"use strict";var t={134:(t,e,i)=>{i.d(e,{SVGNS:()=>s,createSVGGroupChild:()=>o,drawSVGPath:()=>n,drawSVGText:()=>r,highlightElement:()=>l,resetElementHighlight:()=>u,setBlinkAnimation:()=>a,setStroke:()=>h});const s="http://www.w3.org/2000/svg";function n(t,e,i,n,r,o,a=1){const h=document.createElementNS(s,"path");return h.setAttributeNS(null,"d",e),h.setAttributeNS(null,"transform",`translate(${i}, ${n}) scale(${r}, ${o})`),a<1&&h.setAttributeNS(null,"opacity",`${a}`),t.appendChild(h),h}function r(t,e,i,n,r,o="normal",a="middle",h="middle",l="currentColor",u=1){const c=document.createElementNS(s,"text");c.setAttributeNS(null,"font-family","sans-serif"),c.setAttributeNS(null,"font-size",r),c.setAttributeNS(null,"font-weight",o),c.setAttributeNS(null,"x",`${i}`),c.setAttributeNS(null,"y",`${n}`),c.setAttributeNS(null,"text-anchor",a),c.setAttributeNS(null,"dominant-baseline",h),"currentColor"!==l&&c.setAttributeNS(null,"fill",l),u<1&&c.setAttributeNS(null,"opacity",`${u}`);const d=document.createTextNode(e);return c.appendChild(d),t.appendChild(c),c}function o(t,e){const i=document.createElementNS(s,"g");return e&&i.setAttribute("data-id",e),t.appendChild(i),i}function a(t,e=!0,i="1s"){let n=t.querySelector('animate[attributeName="opacity"]');return e?n?(n.setAttributeNS(null,"repeatCount","indefinite"),n.beginElement()):(n=document.createElementNS(s,"animate"),n.setAttributeNS(null,"attributeName","opacity"),n.setAttributeNS(null,"values","1;0.2;1"),n.setAttributeNS(null,"keyTimes","0;0.5;1"),n.setAttributeNS(null,"dur",i),n.setAttributeNS(null,"repeatCount","indefinite"),t.appendChild(n)):(n&&(n.endElement(),n.setAttributeNS(null,"repeatCount","0"),t.style.opacity="1"),t.style.opacity="1"),t}function h(t,e,i){t.setAttributeNS(null,"stroke",e),t.setAttributeNS(null,"stroke-width",`${i}`)}function l(t,e){const i=[];return t.matches("text, path")&&i.push(t),t.querySelectorAll("text, path").forEach((t=>{i.push(t)})),i.forEach((t=>{"none"!==t.getAttribute("fill")&&t.setAttribute("fill",e)})),t}function u(t,e){t.querySelectorAll("text, path").forEach((t=>{"none"!==t.getAttribute("fill")&&t.setAttribute("fill",e)}))}},240:(t,e,i)=>{i.d(e,{AUGMENTATION_DASH_FACTOR:()=>h,COMPACT_SPACING_FACTOR:()=>n,DOT_SIZE_FACTOR:()=>a,DURATION_LINE_SCALES:()=>c,FONT_SIZE_MULTIPLIER:()=>l,LINE_STROKE_WIDTH:()=>s,OCTAVE_DOT_OFFSET_FACTOR:()=>o,SMALL_FONT_SIZE_MULTIPLIER:()=>u,UNDERLINE_SPACING_FACTOR:()=>r});const s=1,n=1.5,r=.2,o=1,a=.1,h=.8,l=1.2,u=.75,c=new Map([[1,1.78],[2,1.6],[3,1.3],[4,1.15]])},559:(t,e,i)=>{i.d(e,{MAJOR_SCALE_INTERVALS:()=>o,MAX_QUARTER_DIVISION:()=>n,MIDDLE_C_MIDI:()=>a,MIN_RESOLUTION:()=>s,PITCH_CLASS_NAMES:()=>r});const s=.0625,n=240,r=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"],o={0:1,2:2,4:3,5:4,7:5,9:6,11:7},a=60},765:(t,e,i)=>{i.d(e,{JianpuBlock:()=>o});var s=i(559);function n(t){return Math.abs(t)<1e-6}function r(t,e){const i=t.start+t.length;if(e<=t.start||e>=i||n(i-e))return null;const s=i-e;t.length=e-t.start;const r={start:e,length:s,pitch:t.pitch,intensity:t.intensity,jianpuNumber:t.jianpuNumber,octaveDot:t.octaveDot,accidental:0,tiedFrom:t};return t.tiedTo&&(r.tiedTo=t.tiedTo,t.tiedTo.tiedFrom=r),t.tiedTo=r,r}class o{start;length;notes;measureNumber;durationLines;augmentationDots;augmentationDash;beatBegin;beatEnd;isTieStart;isTieEnd;constructor(t=0,e=0,i=[],s=1){this.start=t,this.length=e,this.notes=i,this.measureNumber=s}addNote(t){if(0===this.notes.length)return this.start=t.start,this.length=t.length,this.notes.push(t),!0;if(!n(this.start-t.start))return console.warn(`JianpuBlock: Attempted to add note at ${t.start} to block starting at ${this.start}. Ignoring.`),!1;let e=!1,i=!1;for(let s=0;s<this.notes.length;s++)if(this.notes[s].pitch===t.pitch){i=!0,t.length<this.notes[s].length&&(this.notes[s].tiedFrom&&(t.tiedFrom=this.notes[s].tiedFrom,t.tiedFrom&&(t.tiedFrom.tiedTo=t)),this.notes[s].tiedTo&&(t.tiedTo=this.notes[s].tiedTo,t.tiedTo&&(t.tiedTo.tiedFrom=t)),this.notes[s]=t,e=!0);break}i||this.notes.push(t);let s=1/0;for(const t of this.notes)s=Math.min(s,t.length);return this.length=s,!i||e}split(t,e){const i=this.start+this.length;if(t<=this.start||t>=i||n(i-t))return null;const s=i-t,a=t-this.start,h=new o(t,s,[],e.measureNumberAtQ(t)),l=[];for(const e of this.notes){const i=e.start+e.length;if(i>t+1e-6){const i=r(e,t);i?l.push(i):console.warn("Split failed for note, unexpected state.")}else n(i-t)}return l.forEach((t=>h.addNote(t))),this.length=a,delete this.durationLines,delete this.augmentationDots,delete this.augmentationDash,this.beatEnd&&(h.beatEnd=!0,delete this.beatEnd),this.isTieEnd&&(h.isTieStart=!0,delete this.isTieEnd),h}splitToBeat(t){const e=t.timeSignatureAtQ(this.start);if(!e)return null;const i=t.measureLengthAtQ(this.start),s=t.measureNumberAtQ(this.start),r=this.start-(s-Math.floor(s))*i,o=this.start-r,a=4/e.denominator,h=o/a;this.beatBegin=n(h-Math.round(h));const l=r+(Math.floor(h+1e-6)+1)*a,u=r+i,c=this.start+this.length;let d=null;l<c-1e-6&&l>this.start+1e-6&&(d=l),u<c-1e-6&&u>this.start+1e-6&&(null===d||u<d)&&(d=u);let m=null;if(null!==d)m=this.split(d,t),m&&(this.beatEnd=!0);else{const t=(o+this.length)/a;this.beatEnd=n(t-Math.round(t)),this.beatEnd||(this.beatEnd=n(c-u))}return this.isTieStart=this.notes.some((t=>t.tiedFrom)),this.isTieEnd=this.notes.some((t=>t.tiedTo)),m&&(m.isTieStart=m.notes.some((t=>t.tiedFrom)),m.isTieEnd=m.notes.some((t=>t.tiedTo)),this.notes.some((t=>t.tiedTo&&t.start+t.length>d))&&delete this.isTieEnd),m}calculateRenderProperties(t){delete this.durationLines,delete this.augmentationDots,delete this.augmentationDash;const e=this.length;if(n(e)||e<0)return;if(t.allowDottedRests||this.notes.length>0){if(n(e-1.5))return void(this.augmentationDots=1);if(n(e-.75))return this.durationLines=1,void(this.augmentationDots=1);if(n(e-.375))return this.durationLines=2,void(this.augmentationDots=1);n(e-3)&&(this.augmentationDots=1)}if(this.durationLines=e>=3.999999||e>=1.999999||e>=.999999?0:e>=.499999?1:e>=.249999?2:e>=.124999?3:4,this.augmentationDash=!1,1===this.notes.length){const e=this.notes[0],i=t.timeSignatureAtQ(this.start);if(!i)return;const s=Math.max(4/i.denominator,1);if(!(this.measureNumber%1<=1e-6)&&e.tiedFrom&&n(e.tiedFrom.length-s)&&e.tiedFrom.pitch===e.pitch&&e.length>=1){let i=!0;if(e.tiedTo){const s=e.start+e.length;i=Math.floor(t.measureNumberAtQ(this.start))===Math.floor(t.measureNumberAtQ(s))&&e.tiedTo.length>=1}i&&(this.augmentationDash=!0)}}}splitToStandardSymbol(t){const e=this.length;if(n(e)||e<s.MIN_RESOLUTION-1e-6)return null;const i=[];t.allowDottedRests||this.notes.length>0?(i.push(6),i.push(4),i.push(3),i.push(2),i.push(1.5),i.push(1),i.push(.75),i.push(.5),i.push(.375),i.push(.25),i.push(.125),i.push(.0625)):(i.push(4),i.push(2),i.push(1),i.push(.5),i.push(.25),i.push(.125),i.push(.0625));let r=0;for(const t of i)if(e>=t-1e-6){r=t;break}n(r)&&(r=s.MIN_RESOLUTION,e<r-1e-6&&e>1e-6&&console.warn(`Block length ${e} is too small, rendering as ${r}`));let o=null;return e>r+1e-6?(o=this.split(this.start+r,t),this.length!==r&&(console.warn(`Adjusting block length after split from ${this.length} to ${r}`),this.length=r)):this.length=r,o}mergeToMap(t){const e=t.get(this.start);e?(this.notes.forEach((t=>e.addNote(t))),0!==this.measureNumber&&(e.measureNumber=this.measureNumber)):t.set(this.start,this)}isMeasureBeginning(){return n(this.measureNumber-Math.floor(this.measureNumber))}}},775:(t,e,i)=>{i.d(e,{MeasuresInfo:()=>r});var s=i(830),n=i(559);class r{measuresInfo;allowDottedRests=!0;constructor(t,e){this.measuresInfo=[];let i=0,r=0,o=0,a=t.tempos[0],h=t.keySignatures[0],l=t.timeSignatures[0],u=1,c=(0,s.getMeasureLength)(l),d=l.start;const m=n.MIN_RESOLUTION;for(let n=0;n<e;n+=m){const e={start:n,measureNumber:u+(n-d)/c,measureLength:c,tempo:a,keySignature:h,timeSignature:l};if(i<t.tempos.length&&Math.abs(t.tempos[i].start-n)<m/2&&(a=t.tempos[i++],e.tempo=a,e.tempoChange=!0),r<t.keySignatures.length&&Math.abs(t.keySignatures[r].start-n)<m/2&&(h=t.keySignatures[r++],e.keySignature=h,e.keyChange=!0),o<t.timeSignatures.length&&Math.abs(t.timeSignatures[o].start-n)<m/2){u+=(t.timeSignatures[o].start-d)/c,u=Math.round(1e3*u)/1e3,l=t.timeSignatures[o++],e.timeSignature=l,c=(0,s.getMeasureLength)(l),e.measureLength=c,e.measureNumber=u,e.timeChange=!0,d=e.start}this.measuresInfo.push(e)}}findIndex(t){return Math.max(0,Math.min(this.measuresInfo.length-1,Math.floor(t/n.MIN_RESOLUTION)))}measureNumberAtQ(t){if(0===this.measuresInfo.length)return 1;const e=this.findIndex(t),i=this.measuresInfo[e],s=(t-i.start)/i.measureLength;return i.measureNumber+s+1e-9}measureLengthAtQ(t){if(0===this.measuresInfo.length)return(0,s.getMeasureLength)(s.DEFAULT_TIME_SIGNATURE);const e=this.findIndex(t);return this.measuresInfo[e].measureLength}tempoAtQ(t,e=!1){if(0===this.measuresInfo.length)return s.DEFAULT_TEMPO.qpm;const i=this.findIndex(t),r=this.measuresInfo[i],o=Math.abs(r.start-t)<n.MIN_RESOLUTION/2;return!e||r.tempoChange&&o?r.tempo.qpm:-1}keySignatureAtQ(t,e=!1){if(0===this.measuresInfo.length)return s.DEFAULT_KEY_SIGNATURE.key;const i=this.findIndex(t),r=this.measuresInfo[i],o=Math.abs(r.start-t)<n.MIN_RESOLUTION/2;return!e||r.keyChange&&o?r.keySignature.key:-1}timeSignatureAtQ(t,e=!1){if(0===this.measuresInfo.length)return s.DEFAULT_TIME_SIGNATURE;const i=this.findIndex(t),r=this.measuresInfo[i],o=Math.abs(r.start-t)<n.MIN_RESOLUTION/2;return!e||r.timeChange&&o?r.timeSignature:null}quartersToTime(t,e){const i=this.tempoAtQ(e);return i<=0?0:t/i*60}timeToQuarters(t,e){const i=this.tempoAtQ(e);if(i<=0)return 0;const s=t*i/60;return Math.round(s*n.MAX_QUARTER_DIVISION)/n.MAX_QUARTER_DIVISION}isBeatStart(t){if(0===this.measuresInfo.length)return!1;const e=this.findIndex(t),i=this.measuresInfo[e],s=i.timeSignature,r=(t-(i.start-(i.measureNumber-Math.floor(i.measureNumber))*i.measureLength))/(4/s.denominator);return Math.abs(r-Math.round(r))<n.MIN_RESOLUTION/2}}},830:(t,e,i)=>{i.d(e,{DEFAULT_KEY_SIGNATURE:()=>n,DEFAULT_TEMPO:()=>s,DEFAULT_TIME_SIGNATURE:()=>r,getMeasureLength:()=>o});const s={start:0,qpm:60},n={start:0,key:0},r={start:0,numerator:4,denominator:4};function o(t){return t.numerator*(4/t.denominator)}},849:(t,e,i)=>{i.d(e,{JianpuModel:()=>a});var s=i(830),n=i(775),r=i(765),o=i(559);class a{jianpuInfo;measuresInfo;jianpuBlockMap;lastQ;constructor(t,e){this.jianpuInfo=t,this.jianpuBlockMap=new Map,this.lastQ=0,this.update(t,e)}isLastMeasureAtQ(t){return t>=this.lastQ-1e-6}getTotalDuration(){return this.lastQ}update(t,e){this.jianpuInfo=t,t.notes.sort(((t,e)=>t.start-e.start)),this.lastQ=0,t.notes.forEach((t=>{this.lastQ=Math.max(this.lastQ,t.start+t.length)})),this.lastQ+=1e-6,t.tempos=t.tempos&&t.tempos.length?t.tempos:[s.DEFAULT_TEMPO],t.tempos.sort(((t,e)=>t.start-e.start)),t.tempos[0].start>1e-6&&t.tempos.unshift({...s.DEFAULT_TEMPO,start:0});const i=void 0!==e?{start:0,key:e}:{...s.DEFAULT_KEY_SIGNATURE};t.keySignatures=t.keySignatures&&t.keySignatures.length?t.keySignatures:[i],t.keySignatures.sort(((t,e)=>t.start-e.start)),t.keySignatures[0].start>1e-6&&t.keySignatures.unshift({...i,start:0}),t.timeSignatures=t.timeSignatures&&t.timeSignatures.length?t.timeSignatures:[s.DEFAULT_TIME_SIGNATURE],t.timeSignatures.sort(((t,e)=>t.start-e.start)),t.timeSignatures[0].start>1e-6&&t.timeSignatures.unshift({...s.DEFAULT_TIME_SIGNATURE,start:0}),this.measuresInfo=new n.MeasuresInfo(t,this.lastQ),this.infoToBlocks()}infoToBlocks(){const t=new Map;let e=0;if(this.jianpuInfo.notes.forEach((i=>{const s=i.start,n=this.measuresInfo.measureNumberAtQ(s);if(s>e+1e-6){const i=e,n=s-i,o=this.measuresInfo.measureNumberAtQ(i),a=new r.JianpuBlock(i,n,[],o);t.set(i,a)}const o=this.measuresInfo.keySignatureAtQ(s),a=this.createJianpuNote(i,o);let h=t.get(s);h||(h=new r.JianpuBlock(s,0,[],n),t.set(s,h)),h.addNote(a),e=Math.max(e,s+h.length)})),this.lastQ>e+1e-6){const i=e,s=this.lastQ-i;if(s>1e-6){const e=this.measuresInfo.measureNumberAtQ(i),n=new r.JianpuBlock(i,s,[],e);t.set(i,n)}}this.jianpuBlockMap=new Map;const i=Array.from(t.keys()).sort(((t,e)=>t-e));let s=[];i.forEach((e=>{s.push(t.get(e))}));const n=new Set;for(;s.length>0;){let t=s.shift();n.has(t.start)&&this.jianpuBlockMap.has(t.start);let e=t.splitToBeat(this.measuresInfo);if(e){t.mergeToMap(this.jianpuBlockMap),n.add(t.start),s.unshift(e);continue}let i=t,r=null;do{r=i.splitToStandardSymbol(this.measuresInfo),i.mergeToMap(this.jianpuBlockMap),n.add(i.start),r&&(i=r)}while(r)}this.jianpuBlockMap.forEach((t=>{t.calculateRenderProperties(this.measuresInfo)}))}createJianpuNote(t,e){const i=function(t,e){const i=e%12;let s=o.MIDDLE_C_MIDI+i;i>o.MIDDLE_C_MIDI%12&&(s-=12);const n=Math.round((t-s)/12),r=(t-(s+12*n)+12)%12;let a=o.MAJOR_SCALE_INTERVALS[r],h=0;if(void 0===a){switch(r){case 1:a=o.MAJOR_SCALE_INTERVALS[0],h=1;break;case 3:a=o.MAJOR_SCALE_INTERVALS[4],h=2;break;case 6:a=o.MAJOR_SCALE_INTERVALS[5],h=1;break;case 8:a=o.MAJOR_SCALE_INTERVALS[9],h=2;break;case 10:a=o.MAJOR_SCALE_INTERVALS[11],h=2;break;default:{console.warn(`Unexpected chromatic interval ${r} in mapMidiToJianpu. Defaulting to sharp of lower valid degree.`);const i=(r-1+12)%12,s=(r+1+12)%12,n=o.MAJOR_SCALE_INTERVALS[i],l=o.MAJOR_SCALE_INTERVALS[s];void 0!==n?(a=n,h=1):void 0!==l?(a=l,h=2):(a=1,h=1,console.error(`Could not determine Jianpu number components for MIDI ${t}, interval ${r} from tonic in key ${e}.`));break}}void 0===a&&(console.error(`Jianpu number became undefined for MIDI ${t} (interval ${r}, key ${e}) after chromatic processing. This indicates a logic error or misconfigured MAJOR_SCALE_INTERVALS.`),a=1,h=1)}const l=Math.floor((t-s)/12);return{jianpuNumber:a,octaveDot:l,accidental:h}}(t.pitch,e);return{...t,jianpuNumber:i.jianpuNumber,octaveDot:i.octaveDot,accidental:i.accidental}}}},961:(t,e,i)=>{i.d(e,{ACCIDENTAL_TEXT:()=>n,PATH_SCALE:()=>s,augmentationDashPath:()=>a,barPath:()=>r,dotPath:()=>l,tiePath:()=>h,underlinePath:()=>o});const s=100,n=["","#","b"],r="m 0,-50 v 100",o="m 0,0 h 100",a="m 0,0 h 50",h="M -13,5 C 15,-15 65,-15 90,5 C 65,-25 15,-25 -13,5 Z",l="M 0 0 a 15 15 0 1 0 0.0001 0 z"}},e={};function i(s){var n=e[s];if(void 0!==n)return n.exports;var r=e[s]={exports:{}};return t[s](r,r.exports,i),r.exports}i.d=(t,e)=>{for(var s in e)i.o(e,s)&&!i.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:e[s]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var s={};i.r(s),i.d(s,{JianpuSVGRender:()=>c,ScrollType:()=>n});var n,r=i(240),o=i(134),a=i(961),h=i(830),l=i(849),u=i(559);!function(t){t[t.PAGE=0]="PAGE",t[t.NOTE=1]="NOTE",t[t.BAR=2]="BAR"}(n||(n={}));class c{jianpuInfo;jianpuModel;config;height;width;parentElement;div;mainSVG;mainG;musicG;signaturesG;overlaySVG;overlayG;signaturesBlinking;lastKnownScrollLeft;isScrolling;currentKey;currentTimeSignature;playingNotes;lastRenderedQ;estimatedNoteWidth;numberFontSize;smallFontSize;yBaseline;parseColorString(t){return/^[a-z]+$/i.test(t)||t.startsWith("rgb(")?t:/^\d+,\s*\d+,\s*\d+$/.test(t)?`rgb(${t})`:t}constructor(t,e,i){this.jianpuInfo=t,this.div=i;this.config={noteHeight:e.noteHeight??20,noteSpacingFactor:e.noteSpacingFactor??r.COMPACT_SPACING_FACTOR,pixelsPerTimeStep:e.pixelsPerTimeStep??0,noteColor:this.parseColorString(e.noteColor??"black"),activeNoteColor:this.parseColorString(e.activeNoteColor??"red"),defaultKey:e.defaultKey??0,scrollType:e.scrollType??n.PAGE,fontFamily:e.fontFamily??"sans-serif",width:e.width??0,height:e.height??0},this.jianpuModel=new l.JianpuModel(this.jianpuInfo,this.config.defaultKey),this.currentKey=this.jianpuModel.measuresInfo.keySignatureAtQ(0),this.currentTimeSignature=this.jianpuModel.measuresInfo.timeSignatureAtQ(0)??h.DEFAULT_TIME_SIGNATURE,this.playingNotes=new Map,this.lastRenderedQ=-1,this.signaturesBlinking=!1,this.lastKnownScrollLeft=0,this.isScrolling=!1,this.numberFontSize=this.config.noteHeight*r.FONT_SIZE_MULTIPLIER,this.smallFontSize=this.config.noteHeight*r.SMALL_FONT_SIZE_MULTIPLIER,this.estimatedNoteWidth=.6*this.numberFontSize,this.yBaseline=1.5*this.config.noteHeight,this.height=0,this.width=0,this.clear(),this.redraw()}clear(){for(;this.div.lastChild;)this.div.removeChild(this.div.lastChild);this.div.style.position="relative",this.div.style.overflow="hidden",this.overlaySVG=document.createElementNS(o.SVGNS,"svg"),this.overlaySVG.style.position="absolute",this.overlaySVG.style.left="0",this.overlaySVG.style.top="0",this.overlaySVG.style.pointerEvents="none",this.div.appendChild(this.overlaySVG),this.overlayG=(0,o.createSVGGroupChild)(this.overlaySVG,"overlay"),this.parentElement=document.createElement("div"),this.parentElement.style.overflowX="auto",this.parentElement.style.overflowY="hidden",this.parentElement.style.width="100%",this.parentElement.style.height="100%",this.div.appendChild(this.parentElement),this.parentElement.addEventListener("scroll",this.handleScrollEvent),this.mainSVG=document.createElementNS(o.SVGNS,"svg"),this.mainSVG.style.display="block",this.parentElement.appendChild(this.mainSVG),this.mainG=(0,o.createSVGGroupChild)(this.mainSVG,"main-content"),this.signaturesG=(0,o.createSVGGroupChild)(this.mainG,"signatures"),this.musicG=(0,o.createSVGGroupChild)(this.mainG,"music"),this.playingNotes.clear(),this.lastRenderedQ=-1,this.signaturesBlinking=!1,this.lastKnownScrollLeft=0,this.isScrolling=!1,this.height=this.config.height>0?this.config.height:5*this.config.noteHeight,this.width=this.config.width>0?this.config.width:0,this.currentKey=this.jianpuModel.measuresInfo.keySignatureAtQ(0),this.currentTimeSignature=this.jianpuModel.measuresInfo.timeSignatureAtQ(0)??h.DEFAULT_TIME_SIGNATURE,this.drawSignatures(this.overlayG,0,!0,!0),this.updateLayout()}updateLayout(t){this.width=t??this.width,this.config.width>0&&(this.width=this.config.width),this.height=Math.max(this.height,6*this.config.noteHeight),this.config.height>0&&(this.height=this.config.height);const e=1.65*this.config.noteHeight;this.mainSVG.setAttribute("width",`${this.width}`),this.mainSVG.setAttribute("height",`${this.height}`),this.mainG.setAttribute("transform",`translate(0, ${this.yBaseline+e})`),this.overlaySVG.setAttribute("width","200"),this.overlaySVG.setAttribute("height",`${this.height}`),this.overlayG.setAttribute("transform",`translate(0, ${this.yBaseline})`)}redraw(t,e){let i=-1;const s=this.config.pixelsPerTimeStep<=0;if(t){const r=`${t.start}-${t.pitch}`;if(this.playingNotes.forEach(((t,e)=>{if(e!==r){const t=this.mainSVG.querySelector(`g[data-id="${e}"]`);t&&(0,o.resetElementHighlight)(t,this.config.noteColor),this.playingNotes.delete(e)}})),!this.playingNotes.has(r)){const s=this.mainSVG.querySelector(`g[data-id="${r}"]`);if(s){(0,o.highlightElement)(s,this.config.activeNoteColor),this.playingNotes.set(r,t);const a=s.getBoundingClientRect(),h=this.mainSVG.getBoundingClientRect();i=a.left-h.left+this.parentElement.scrollLeft;const l=s.hasAttribute("data-is-measure-start");e&&(this.config.scrollType!==n.BAR||l)&&this.scrollIntoViewIfNeeded(i)}}if(!s&&this.signaturesBlinking){const e=this.overlayG.getBoundingClientRect().width;this.jianpuModel.measuresInfo.quartersToTime(t.start,t.start)*this.config.pixelsPerTimeStep>e&&(this.signaturesBlinking=!1,(0,o.setBlinkAnimation)(this.overlayG,!1))}}else{this.jianpuModel.update(this.jianpuInfo,this.config.defaultKey);let t=this.width,e=this.width,i=this.height>0?this.height-this.yBaseline:3*this.config.noteHeight,n=0;const r=new Map;this.jianpuModel.jianpuBlockMap.forEach(((o,a)=>{if(a>=this.lastRenderedQ-1e-9){t=s?e:this.jianpuModel.measuresInfo.quartersToTime(a,a)*this.config.pixelsPerTimeStep;const h=this.drawJianpuBlock(o,t,r);s?e+=h:e=Math.max(e,t+h);const l=this.mainSVG.querySelector(`g[data-block-start="${o.start}"]`);if(l)try{const t=l.getBBox(),e=t.y,s=t.y+t.height;n=Math.min(n,e),i=Math.max(i,s)}catch(t){}this.lastRenderedQ=a+o.length}})),this.height=Math.max(this.height,i-n+this.config.noteHeight),this.updateLayout(e)}return i}drawJianpuBlock(t,e,i){let s=0;const n=this.config.pixelsPerTimeStep<=0,h=t.isMeasureBeginning(),l=(0,o.createSVGGroupChild)(this.musicG,`block-${t.start}`);if(l.setAttribute("data-block-start",`${t.start}`),h&&t.start>1e-6){const t=e-(n?.6*this.estimatedNoteWidth:4),i=2*this.config.noteHeight,h=0,l=(0,o.drawSVGPath)(this.musicG,a.barPath,t,h,1,i/a.PATH_SCALE);(0,o.setStroke)(l,this.config.noteColor,r.LINE_STROKE_WIDTH),n&&(s+=r.LINE_STROKE_WIDTH)}const u=this.updateCurrentKey(t.start),c=this.updateCurrentTimeSignature(t.start);let d=0;if((u||c)&&t.start>1e-6){const t=e+s;d=this.drawSignatures(this.signaturesG,t,u,c),n&&(s+=d+.2*this.estimatedNoteWidth)}const m=e+s;let g=0;if(t.notes.length>0?g=this.drawNotes(t,m,i,l):t.length>1e-6&&(g=this.drawRest(t,m,l)),n){s+=g;let e=this.estimatedNoteWidth*this.config.noteSpacingFactor;t.beatEnd?e*=1:t.length<.0625?e*=.05:t.length<.125?e*=.1:t.length<.25?e*=.2:t.length<.5?e*=.4:t.length<1&&(e*=.5),s+=e}else s=Math.max(d,g);if(this.jianpuModel.isLastMeasureAtQ(t.start+t.length)){const t=e+s,i=2*this.config.noteHeight,h=0,l=(0,o.drawSVGPath)(this.musicG,a.barPath,t,h,1,i/a.PATH_SCALE);(0,o.setStroke)(l,this.config.noteColor,r.LINE_STROKE_WIDTH),n&&(s+=r.LINE_STROKE_WIDTH)}return s}drawNotes(t,e,i,s){let n=e,h=e;const l=.1*this.estimatedNoteWidth,u=`${this.numberFontSize}px`,c=`${this.smallFontSize}px`,{durationLines:d=0,augmentationDots:m=0,augmentationDash:g=!1}=t;return t.notes.forEach((e=>{const S=`${e.start}-${e.pitch}`,f=(0,o.createSVGGroupChild)(s,S);t.isMeasureBeginning()&&f.setAttribute("data-is-measure-start","true");let p=n,T=p;if(0!==e.accidental){const t=a.ACCIDENTAL_TEXT[e.accidental];(0,o.drawSVGText)(f,t,p+l,0,c,"normal","end","text-top",this.config.noteColor)}let A=0;if(g){const t=this.config.noteHeight*r.AUGMENTATION_DASH_FACTOR,e=t/50,i=(0,o.drawSVGPath)(f,a.augmentationDashPath,p,0,e,1);(0,o.setStroke)(i,this.config.noteColor,r.LINE_STROKE_WIDTH),A=t,T=p+A}else{const t=`${e.jianpuNumber}`;A=(0,o.drawSVGText)(f,t,p,0,u,"normal","start","middle",this.config.noteColor).getBBox().width,T=p+A}if(0!==e.octaveDot&&!1===g){const t=this.config.noteHeight*r.DOT_SIZE_FACTOR,i=t/(.15*a.PATH_SCALE),s=p+A/2,n=2.8*t,h=this.config.noteHeight*r.OCTAVE_DOT_OFFSET_FACTOR;for(let t=0;t<Math.abs(e.octaveDot);t++){const r=(e.octaveDot>0?-h:.6*h)-t*n*(e.octaveDot>0?1:-1);(0,o.drawSVGPath)(f,a.dotPath,s,r,i,i)}}if(d>0){const t=this.config.noteHeight*r.UNDERLINE_SPACING_FACTOR*2.5,e=this.config.noteHeight*r.UNDERLINE_SPACING_FACTOR,i=A/a.PATH_SCALE*(r.DURATION_LINE_SCALES.get(d)??1);for(let s=0;s<d;s++){const n=t+s*e,h=(0,o.drawSVGPath)(f,a.underlinePath,p,n,i,1);(0,o.setStroke)(h,this.config.noteColor,r.LINE_STROKE_WIDTH)}}let E=T+l;if(m>0){const t=this.config.noteHeight*r.DOT_SIZE_FACTOR,e=t/(.15*a.PATH_SCALE);for(let i=0;i<m;i++)(0,o.drawSVGPath)(f,a.dotPath,E,0,e,e),E+=t+l;T=E+l}const I=T;if(e.tiedTo&&!g)i.set(e,{g:f,xNoteRight:I,yNoteBaseline:0});else if(e.tiedFrom){let t=e.tiedFrom;for(;t.tiedFrom;)t=t.tiedFrom;const s=i.get(t);if(s){const n=1*s.xNoteRight,r=(g?p-2.2*this.estimatedNoteWidth:p-l)-n,h=1.2*-this.config.noteHeight,u=r/a.PATH_SCALE*1.3,c=this.config.noteHeight/a.PATH_SCALE*1.6;r>1&&(0,o.drawSVGPath)(s.g,a.tiePath,n-(s.g.getCTM()?.e??0),h,u,c);let d=t;for(;d&&d!==e;){i.delete(d);const t=d.tiedTo;t&&(d=t)}}else console.warn("Missing linked SVG details for first tied note:",t)}h=Math.max(h,T)})),h-e}drawRest(t,e,i){const s=`${this.numberFontSize}px`,n=.1*this.estimatedNoteWidth,{durationLines:h=0,augmentationDots:l=0}=t;let u=e,c=u;const d=(0,o.drawSVGText)(i,"0",u,0,s,"normal","start","middle",this.config.noteColor).getBBox().width;if(c=u+d,h>0){const t=this.config.noteHeight*r.UNDERLINE_SPACING_FACTOR*2.5,e=this.config.noteHeight*r.UNDERLINE_SPACING_FACTOR,s=d/a.PATH_SCALE*(r.DURATION_LINE_SCALES.get(h)??1);for(let n=0;n<h;n++){const h=t+n*e,l=(0,o.drawSVGPath)(i,a.underlinePath,u,h,s,1);(0,o.setStroke)(l,this.config.noteColor,r.LINE_STROKE_WIDTH)}}let m=c+n;if(l>0){const t=this.config.noteHeight*r.DOT_SIZE_FACTOR,e=t/(.15*a.PATH_SCALE);for(let s=0;s<l;s++)(0,o.drawSVGPath)(i,a.dotPath,m,0,e,e),m+=t+n;c=m+n}return c-e}drawSignatures(t,e,i,s){let n=e;const r=.3*this.estimatedNoteWidth,a=`${this.smallFontSize}px`,h=`${this.numberFontSize}px`;if(i){const e=`1=${u.PITCH_CLASS_NAMES[this.currentKey%12]??"C"}`;n+=(0,o.drawSVGText)(t,e,n,0,h,"normal","start","middle",this.config.noteColor).getBBox().width+2*r}if(s){const e=`${this.currentTimeSignature.numerator}/${this.currentTimeSignature.denominator}`;n+=(0,o.drawSVGText)(t,e,n,0,a,"normal","start","middle",this.config.noteColor).getBBox().width+r}const l=n-e;try{const e=t.getBBox(),i=e.y,s=e.y+e.height,n=Math.max(this.yBaseline+s,this.yBaseline-i)+.5*this.config.noteHeight;this.height=Math.max(this.height,n)}catch(t){}return t===this.overlayG&&this.config.pixelsPerTimeStep>0&&(this.signaturesBlinking=!0,(0,o.setBlinkAnimation)(this.overlayG,!0)),l}updateCurrentKey(t){const e=this.jianpuModel.measuresInfo.keySignatureAtQ(t,!0);return-1!==e&&e!==this.currentKey&&(this.currentKey=e,!0)}updateCurrentTimeSignature(t){const e=this.jianpuModel.measuresInfo.timeSignatureAtQ(t,!0);return!(!e||e.numerator===this.currentTimeSignature.numerator&&e.denominator===this.currentTimeSignature.denominator)&&(this.currentTimeSignature=e,!0)}handleScrollEvent=t=>{this.lastKnownScrollLeft=this.parentElement.scrollLeft,this.isScrolling||window.requestAnimationFrame((()=>{this.updateOverlaySignaturesForScroll(this.lastKnownScrollLeft),this.isScrolling=!1})),this.isScrolling=!0};scrollIntoViewIfNeeded(t){const e=this.parentElement.getBoundingClientRect().width,i=this.parentElement.scrollLeft;let s=i;if(this.config.scrollType===n.PAGE){const n=20;t<i+n?s=t-n:t>i+e-n&&(s=t-e+n)}else{s=t-.5*e}s=Math.max(0,Math.min(s,this.parentElement.scrollWidth-e)),Math.abs(s-i)>1&&(this.parentElement.scrollTo({left:s,behavior:"smooth"}),this.updateOverlaySignaturesForScroll(s))}updateOverlaySignaturesForScroll(t){const e=this.pixelsToTime(t),i=this.jianpuModel.measuresInfo.keySignatureAtQ(e),s=this.jianpuModel.measuresInfo.timeSignatureAtQ(e)??this.currentTimeSignature;let n=!1;if(i!==this.currentKey&&(this.currentKey=i,n=!0),s.numerator===this.currentTimeSignature.numerator&&s.denominator===this.currentTimeSignature.denominator||(this.currentTimeSignature=s,n=!0),n){for(;this.overlayG.lastChild;)this.overlayG.removeChild(this.overlayG.lastChild);this.drawSignatures(this.overlayG,0,!0,!0),t<10&&this.config.pixelsPerTimeStep>0?((0,o.setBlinkAnimation)(this.overlayG,!0),this.signaturesBlinking=!0):this.config.pixelsPerTimeStep>0&&((0,o.setBlinkAnimation)(this.overlayG,!1),this.signaturesBlinking=!1)}}pixelsToTime(t){return this.config.pixelsPerTimeStep<=0?0:this.jianpuModel.measuresInfo.timeToQuarters(t/this.config.pixelsPerTimeStep,0)}}return s})()));