1// abc2svg - ABC to SVG translator 2// @source: https://chiselapp.com/user/moinejf/repository/abc2svg 3// Copyright (C) 2014-2020 Jean-Francois Moine - LGPL3+ 4//jianpu.js-module to output jiănpŭ(简谱)music sheets 5abc2svg.jianpu={k_tb:["Cb","Gb","Db","Ab","Eb","Bb","F","C","G","D","A","E","B","F#","C#"],cde2fcg:new Int8Array([0,2,4,-1,1,3,5]),cgd2cde:new Int8Array([0,-4,-1,-5,-2,-6,-3,0,-4,-1,-5,-2,-6,-3,0]),acc2:new Int8Array([-2,-1,3,1,2]),acc_tb:["\ue264","\ue260",,"\ue262","\ue263","\ue261"],do_pscom:function(of,p){switch(p.match(/\w+/)[0]){case'staves':case'score':p=p.replace(/\(|\)/g,'') 6break} 7of(p)},output_music:function(of){var C=abc2svg.C,abc=this,cur_sy=abc.get_cur_sy(),voice_tb=abc.get_voice_tb() 8if(!abc.cfmt().jianpu){of() 9return} 10function set_head(){var tsfirst=abc.get_tsfirst(),p_v=voice_tb[0],mt=p_v.meter.a_meter[0],sk=p_v.key,s={type:C.BLOCK,subtype:"text",dur:0,v:0,p_v:p_v,st:0,seqst:true,text:(sk.k_mode+1)+"="+ 11(abc2svg.jianpu.k_tb[sk.k_sf+7+ 12abc2svg.jianpu.cde2fcg[sk.k_mode]])},s2=voice_tb[0].sym 13if(mt) 14s.text+=' '+(mt.bot?(mt.top+'/'+mt.bot):mt.top) 15s2.prev=s 16s.next=s2 17voice_tb[0].sym=s 18tsfirst.ts_prev=s 19s.ts_next=tsfirst 20abc.set_tsfirst(s)} 21function slice(s){var n,s2,s3 22if(s.dur>=C.BLEN) 23n=3 24else if(s.dur==C.BLEN/2) 25n=1 26else 27n=2 28while(--n>=0){s2={type:C.REST,v:s.v,p_v:s.p_v,st:s.st,dur:C.BLEN/4,dur_orig:C.BLEN/4,stem:0,multi:0,nhd:0,notes:[{pit:s.notes[0].pit,jn:8}],xmx:0,noplay:true,time:s.time+C.BLEN/4,prev:s,next:s.next} 29s.next=s2 30if(s2.next) 31s2.next.prev=s2 32if(!s.ts_next){s.ts_next=s2 33if(s.soln) 34s.soln=false 35s2.ts_prev=s 36s2.seqst=true}else{for(s3=s.ts_next;s3;s3=s3.ts_next){if(s3.time<s2.time) 37continue 38if(s3.time>s2.time){s2.seqst=true 39s3=s3.ts_prev} 40s2.ts_next=s3.ts_next 41s2.ts_prev=s3 42if(s2.ts_next) 43s2.ts_next.ts_prev=s2 44s3.ts_next=s2 45break}} 46s=s2}} 47function set_sym(p_v){var s,s2,note,pit,nn,p,a,m,i,sf=p_v.key.k_sf 48delta=abc2svg.jianpu.cgd2cde[sf+7]-2 49p_v.key.k_a_acc=[] 50p_v.clef.invis=true 51for(s=p_v.sym;s;s=s.next){s.st=p_v.st 52switch(s.type){case C.CLEF:s.invis=true 53default:continue 54case C.KEY:delta=abc2svg.jianpu.cgd2cde[s.k_sf+7]-2 55s.a_gch=[{type:'@',font:abc.get_font("annotation"),wh:[10,10],x:-5,y:30,text:(s.k_mode+1)+"="+ 56(abc2svg.jianpu.k_tb[s.k_sf+7+ 57abc2svg.jianpu.cde2fcg[s.k_mode]])}] 58continue 59case C.REST:if(s.notes[0].jn) 60continue 61s.notes[0].jn=0 62if(s.dur>=C.BLEN/2) 63slice(s) 64continue 65case C.NOTE:break} 66s.stem=-1 67s.stemless=true 68if(s.sls){for(i=0;i<s.sls.length;i++) 69s.sls[i].ty=C.SL_ABOVE} 70for(m=0;m<=s.nhd;m++){note=s.notes[m] 71p=note.pit 72pit=p+delta 73note.jn=((pit+77)%7)+1 74note.pit=25 75note.jo=(pit/7)|0 76a=note.acc 77if(a){nn=abc2svg.jianpu.cde2fcg[(p+5+16*7)%7]-sf 78if(a!=3) 79nn+=a*7 80nn=((((nn+1+21)/7)|0)+2-3+32*5)%5 81note.acc=abc2svg.jianpu.acc2[nn]} 82if(note.sls){for(i=0;i<note.sls.length;i++) 83note.sls[i].ty=C.SL_ABOVE} 84if(note.tie_ty) 85note.tie_ty=C.SL_ABOVE} 86if(s.dur>=C.BLEN/2) 87slice(s) 88if(s.a_dd){for(i=0;i<s.a_dd.length;i++){if(s.a_dd[i].glyph=="stc"){abc.deco_cnv(["gstc"],s) 89s.a_dd[i]=s.a_dd.pop()}}}}} 90set_head() 91for(v=0;v<voice_tb.length;v++) 92set_sym(voice_tb[v]) 93of()},draw_symbols:function(of,p_voice){var i,m,nl,note,s,s2,x,y,C=abc2svg.C,abc=this,dot="\ue1e7",staff_tb=abc.get_staff_tb(),out_svg=abc.out_svg,out_sxsy=abc.out_sxsy,xypath=abc.xypath 94if(!abc.cfmt().jianpu){of(p_voice) 95return} 96function draw_dur(s1,y,s2,n,nl){var s,s3 97xypath(s1.x-3,y+5) 98out_svg('h'+(s2.x-s1.x+8).toFixed(1)+'"/>\n') 99y-=2.5 100while(++n<=nl){s=s1 101while(1){if(s.nflags&&s.nflags>=n){s3=s 102while(s!=s2){if(s.next.beam_br1||(s.next.beam_br2&&n>2)||(s.next.nflags&&s.next.nflags<n)) 103break 104s=s.next} 105draw_dur(s3,y,s,n,nl)} 106if(s==s2) 107break 108s=s.next}}} 109function out_mus(x,y,p){out_svg('<text x="') 110out_sxsy(x,'" y="',y) 111out_svg('">'+p+'</text>\n')} 112function out_txt(x,y,p){out_svg('<text class="bn" x="') 113out_sxsy(x,'" y="',y) 114out_svg('">'+p+'</text>\n')} 115function draw_hd(s,x,y){var m,note,ym 116for(m=0;m<=s.nhd;m++){note=s.notes[m] 117out_txt(x-3.5,y+8,"01234567-"[note.jn]) 118if(note.acc) 119out_mus(x-12,y+12,abc2svg.jianpu.acc_tb[note.acc+2]) 120if(note.jo>2){out_mus(x-1,y+22,dot) 121if(note.jo>3){y+=3 122out_mus(x-1,y+22,dot)}}else if(note.jo<2){ym=y+4 123if(m==0&&s.nflags>0) 124ym-=2.5*s.nflags 125out_mus(x-1,ym,dot)} 126y+=20}} 127for(s=p_voice.sym;s;s=s.next){if(s.invis) 128continue 129switch(s.type){case C.METER:abc.draw_meter(s) 130break 131case C.NOTE:case C.REST:x=s.x 132y=staff_tb[s.st].y 133draw_hd(s,x,y) 134if(s.nflags>=0&&s.dots) 135out_mus(x+8,y+13,dot) 136if(s.nflags>0){if(s.beam_st||s.type==C.REST){nl=s.nflags 137s2=s 138while(1){if(s2.nflags&&s2.nflags>nl) 139nl=s2.nflags 140if(s2.beam_end) 141break 142if(!s2.next||!s2.next.nflags||s2.next.nflags<=0) 143break 144s2=s2.next} 145draw_dur(s,y,s2,1,nl)}} 146break}}},set_fmt:function(of,cmd,param){if(cmd=="jianpu"){var cfmt=this.cfmt() 147cfmt.jianpu=true 148cfmt.staffsep=20 149cfmt.sysstaffsep=14 150this.set_v_param("stafflines","...") 151cfmt.tuplets=[0,1,0,1] 152return} 153of(cmd,param)},set_pitch:function(of,last_s){of(last_s) 154if(!last_s||!this.cfmt().jianpu) 155return 156var C=abc2svg.C 157for(var s=this.get_tsfirst();s;s=s.ts_next){switch(s.type){case C.KEY:if(s.prev.type==C.CLEF||s.v!=0) 158s.a_gch=null 159break 160case C.NOTE:s.ymx=20*s.nhd+22 161if(s.notes[s.nhd].jo>2){s.ymx+=3 162if(s.notes[s.nhd].jo>3) 163s.ymx+=2} 164break}}},set_width:function(of,s){of(s) 165if(!this.cfmt().jianpu) 166return 167var w,m,note,C=abc2svg.C 168switch(s.type){case C.CLEF:case C.KEY:s.wl=s.wr=0 169break 170case C.NOTE:for(m=0;m<=s.nhd;m++){note=s.notes[m] 171if(note.acc&&s.wl<14) 172s.wl=14} 173break}},set_hooks:function(abc){abc.do_pscom=abc2svg.jianpu.do_pscom.bind(abc,abc.do_pscom) 174abc.draw_symbols=abc2svg.jianpu.draw_symbols.bind(abc,abc.draw_symbols) 175abc.output_music=abc2svg.jianpu.output_music.bind(abc,abc.output_music) 176abc.set_format=abc2svg.jianpu.set_fmt.bind(abc,abc.set_format) 177abc.set_pitch=abc2svg.jianpu.set_pitch.bind(abc,abc.set_pitch) 178abc.set_width=abc2svg.jianpu.set_width.bind(abc,abc.set_width) 179abc.get_glyphs().gstc='<circle id="gstc" cx="0" cy="-3" r="2"/>' 180abc.get_decos().gstc="0 gstc 5 1 1" 181abc.add_style("\n.bn {font-family:sans-serif; font-size:15px}")}} 182abc2svg.modules.hooks.push(abc2svg.jianpu.set_hooks) 183abc2svg.modules.jianpu.loaded=true 184