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//abc2svg-strtab.js-tablature for string instruments 5abc2svg.strtab={draw_symbols:function(of,p_v){var s,m,not,stb,x,y,C=abc2svg.C,abc=this 6if(!p_v.tab){of(p_v) 7return} 8m=abc.cfmt().bgcolor||"white" 9if(abc.bgt!=m){if(!abc.bgn) 10abc.bgn=1 11else 12abc.bgn++ 13abc.bgt=m 14abc.defs_add('\ 15<filter x="-0.1" y="0.2" width="1.2" height=".8" id="bg'+abc.bgn+'">\n\ 16<feFlood flood-color="'+m+'"/>\n\ 17<feComposite in="SourceGraphic" operator="over"/>\n\ 18</filter>') 19abc.add_style('\n.bg'+abc.bgn+'{filter:url(#bg'+abc.bgn+')}')} 20for(s=p_v.sym;s;s=s.next){switch(s.type){case C.KEY:case C.METER:case C.REST:s.invis=true 21break 22case C.NOTE:if(!s.stemless) 23s.ys=-10 24break}} 25of(p_v) 26abc.glout() 27stb=abc.get_staff_tb()[p_v.st].y 28abc.out_svg('<g class="bn">\n') 29for(s=p_v.sym;s;s=s.next){if(s.type==C.NOTE){for(m=0;m<=s.nhd;m++){not=s.notes[m] 30x=s.x-3 31if(not.nb>=10) 32x-=3 33y=3*(not.pit-18) 34abc.out_svg('<text class="bg'+abc.bgn+'" x="') 35abc.out_sxsy(x,'" y="',stb+y-2.5) 36abc.out_svg('">'+not.nb+'</text>\n')}}} 37abc.out_svg('</g>\n')},set_fmt:function(of,cmd,parm){if(cmd=="strtab"){if(!parm) 38return 39this.set_v_param("clef","tab") 40if(parm.indexOf("diafret")>=0){this.set_v_param("diafret",true) 41parm=parm.replace(/\s*diafret\s*/,"")} 42this.set_v_param("strings",parm) 43return} 44of(cmd,parm)},set_width:function(of,s){var m,not,abc=this,C=abc2svg.C,o=s.stem<0?3.5:-2.5 45of(s) 46if(s.p_v&&s.p_v.tab&&s.type==C.NOTE&&!s.stemless){for(m=0;m<=s.nhd;m++) 47s.notes[m].shhd=o}},set_stems:function(of){var p_v,i,m,nt,n,bi,bn,strss,C=abc2svg.C,abc=this,s=abc.get_tsfirst(),strs=[],lstr=[] 48function set_pit(p_v,s,nt,i){var st=s.st,n=(p_v.diafret?nt.pit:nt.midi)-p_v.tab[i] 49if(p_v.diafret&&nt.acc) 50n+='+' 51nt.acc=0 52nt.invis=true 53nt.pit=i*2+18 54nt.nb=n 55strss[i]=s.time+s.dur 56if(s.nflags>=-1&&!s.stemless){if(!lstr[st]) 57lstr[st]=[10] 58if(lstr[st][0]>i){lstr[st][0]=i 59lstr[st][1]=s} 60s.stemless=true}} 61function strnum(n){n=n.match(/^([1-9])s?$/) 62return n?p_v.tab.length-n[1]:-1} 63p_v=abc.get_voice_tb() 64for(n=0;n<p_v.length;n++){if(!p_v[n].tab) 65continue 66m=p_v[n].capo 67if(m){for(i=0;i<p_v[n].tab.length;i++) 68p_v[n].tab[i]+=m}} 69for(;s;s=s.ts_next){p_v=s.p_v 70if(!p_v.tab) 71continue 72strss=strs[s.st] 73if(!strss) 74strss=strs[s.st]=[] 75switch(s.type){case C.KEY:case C.REST:case C.TIME:s.invis=true 76default:continue 77case C.NOTE:break} 78if(!s.nhd&&s.a_dd){i=s.a_dd.length 79while(--i>=0){bi=strnum(s.a_dd[i].name) 80if(bi>=0){nt=s.notes[0] 81set_pit(p_v,s,nt,bi) 82break}} 83delete s.a_dd} 84ls:for(m=0;m<=s.nhd;m++){nt=s.notes[m] 85if(nt.nb!=undefined) 86continue 87if(nt.a_dcn){i=nt.a_dcn.length 88while(--i>=0){bi=strnum(nt.a_dcn[i]) 89if(bi>=0){set_pit(p_v,s,nt,bi) 90delete nt.a_dcn 91continue ls}} 92delete nt.a_dcn} 93bn=100 94i=p_v.tab.length 95while(--i>=0){if(strss[i]&&strss[i]>s.time) 96continue 97n=(p_v.diafret?nt.pit:nt.midi)- 98p_v.tab[i] 99if(n>=0&&n<bn){bi=i 100bn=n}} 101set_pit(p_v,s,nt,bi)} 102if(!s.ts_next||s.ts_next.time!=s.time){for(i=0;i<lstr.length;i++){if(lstr[i]){delete lstr[i][1].stemless 103lstr[i]=null}}}} 104of()},set_vp:function(of,a){var i,e,g,tab,strs,ok,p_v=this.get_curvoice() 105function abc2tab(p){var i,c,t=[] 106if(p_v.diafret){for(i=0;i<p.length;i++){c=p[i] 107c="CDEFGABcdefgab".indexOf(c) 108if(c<0) 109return 110c+=16 111while(1){if(p[i+1]=="'"){c+=7 112i++}else if(p[i+1]==","){c-=7 113i++}else{break}} 114t.push(c)}}else{for(i=0;i<p.length;i++){c=p[i] 115c="CCDDEFFGGAABccddeffggaab".indexOf(c) 116if(c<0) 117return 118c+=60 119while(1){if(p[i+1]=="'"){c+=12 120i++}else if(p[i+1]==","){c-=12 121i++}else{break}} 122t.push(c)}} 123return t} 124function str2tab(a){var str,p,o,t=[] 125if(p_v.diafret){while(1){str=a.shift() 126if(!str) 127break 128p="CDEFGAB".indexOf(str[0]) 129o=Number(str[1]) 130if(p<0||isNaN(o)) 131return 132t.push(o*7+p-12)}}else{while(1){str=a.shift() 133if(!str) 134break 135p="CCDDEFFGGAAB".indexOf(str[0]) 136o=Number(str[1]) 137if(p<0||isNaN(o)) 138return 139t.push((o+1)*12+p)}} 140return t} 141for(i=0;i<a.length;i++){switch(a[i]){case"clef=":e=a[i+1] 142if(e!="tab") 143break 144a.splice(i,1) 145case"tab":a.splice(i,1) 146i-- 147ok=true 148p_v.pos.stm=abc2svg.C.SL_BELOW 149break 150case"strings=":strs=a[++i] 151ok=true 152break 153case"nostems":p_v.pos.stm=abc2svg.C.SL_HIDDEN 154break 155case"capo=":p_v.capo=Number(a[++i]) 156break 157case"diafret=":i++ 158case"diafret":p_v.diafret=true 159break}} 160if(ok){if(strs){if(strs[1]>='1'&&strs[1]<='9') 161tab=str2tab(strs.split(',')) 162else 163tab=abc2tab(strs) 164if(!tab){this.syntax(1,"Bad strings in tablature") 165ok=false}}else if(!p_v.tab){tab=p_v.diafret?[10,14,17]:[40,45,50,55,59,64]}} 166if(ok){if(p_v.capo){p_v.tab=[] 167for(i=0;i<tab.length;i++) 168p_v.tab.push(tab[i]+p_v.capo)}else{p_v.tab=tab} 169a.push("clef=") 170g=this.get_glyphs() 171if(tab.length==3){a.push('"tab3"') 172if(!g.tab3) 173g.tab3='<text id="tab3"\ 174 x="-4,-4,-4" y="-4,3,10"\ 175 style="font:bold 8px sans-serif">TAB</text>'}else if(tab.length==4){a.push('"tab4"') 176if(!g.tab4) 177g.tab4='<text id="tab4"\ 178 x="-4,-4,-4" y="-8,1,10"\ 179 style="font:bold 12px sans-serif">TAB</text>'}else if(tab.length==5){a.push('"tab5"') 180if(!g.tab5) 181g.tab5='<text id="tab5"\ 182 x="-4,-4,-4" y="-11,-2,7"\ 183 style="font:bold 12px sans-serif">TAB</text>'}else{a.push('"tab6"') 184if(!g.tab6) 185g.tab6='<text id="tab6"\ 186 x="-4,-4,-4" y="-14.5,-4,5.5"\ 187 style="font:bold 13px sans-serif">TAB</text>'} 188a.push("stafflines=") 189a.push("|||||||||".slice(0,tab.length)) 190p_v.staffscale=1.6} 191of(a)},set_hooks:function(abc){abc.draw_symbols=abc2svg.strtab.draw_symbols.bind(abc,abc.draw_symbols) 192abc.set_format=abc2svg.strtab.set_fmt.bind(abc,abc.set_format);abc.set_stems=abc2svg.strtab.set_stems.bind(abc,abc.set_stems) 193abc.set_width=abc2svg.strtab.set_width.bind(abc,abc.set_width) 194abc.set_vp=abc2svg.strtab.set_vp.bind(abc,abc.set_vp) 195var decos=abc.get_decos() 196decos["1s"]="0 nul 0 0 0" 197decos["2s"]="0 nul 0 0 0" 198decos["3s"]="0 nul 0 0 0" 199decos["4s"]="0 nul 0 0 0" 200decos["5s"]="0 nul 0 0 0" 201decos["6s"]="0 nul 0 0 0" 202if(!user.nul) 203user.nul=function(){} 204abc.add_style("\n.bn{font:bold 8px sans-serif}")}} 205abc2svg.modules.hooks.push(abc2svg.strtab.set_hooks) 206abc2svg.modules.strtab.loaded=true 207