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//grid3.js-module to insert a manual chords
5abc2svg.grid3={block_gen:function(of,s){if(s.subtype!="grid"){of(s)
6return}
7var abc=this,cfmt=abc.cfmt(),img=abc.get_img(),txt=s.text,font,font_cl,cls,w,ln,i,lines=[],cl=[],bars=[],cells=[],nr=0,nc=0,wc=0
8function build_grid(){var i,k,l,line,bl,bar,w,hr,x0,x,y,yl,cl,cell,lc='',path='<path class="stroke" stroke-width="1" d="M',sf='" style="font-size:'+(font.size*.72).toFixed(1)+'px'
9function build_ch(cl,x,y,n){return'<text class="'+cl+'" x="'+
10x.toFixed(1)+'" y="'+y.toFixed(1)+'">'+
11cell[n]+'</text>\n'}
12function build_cell(cell,x,y,yl,hr){var line
13if(cell.length>1){line=path+
14(x-wc/2).toFixed(1)+' '+
15yl.toFixed(1)+'l'+
16wc.toFixed(1)+' -'+hr.toFixed(1)+'"/>\n'
17if(cell[1]){line+=path+
18(x-wc/2).toFixed(1)+' '+
19(yl-hr).toFixed(1)+'l'+
20(wc/2).toFixed(1)+' '+(hr/2).toFixed(1)+'"/>\n'+
21build_ch(cls+sf,x-wc/3,y,0)+
22build_ch(cls+sf,x,y-hr*.32,1)}else{line+=build_ch(cls+sf,x-wc*.2,y-hr/4,0)}
23if(cell.length>=3){if(cell[3]){line+=path+
24x.toFixed(1)+' '+
25(yl-hr/2).toFixed(1)+'l'+
26(wc/2).toFixed(1)+' '+(hr/2).toFixed(1)+'"/>\n'+
27build_ch(cls+sf,x,y+hr*.3,2)+
28build_ch(cls+sf,x+wc/3,y,3)}else{line+=build_ch(cls+sf,x+wc*.2,y+hr/4,2)}}}else{line=build_ch(cls,x,y,0)}
29return line}
30hr=font.size*2.1
31if(wc<hr*1.4)
32wc=hr*1.4
33w=wc*nc
34yl=3
35y=3-font.size*.7
36x0=(img.width/cfmt.scale-w)/2
37while(1){cl=cells.shift()
38if(!cl)
39break
40y+=hr
41yl+=hr
42x=x0+wc/2
43while(1){cell=cl.shift()
44if(!cell)
45break
46lc+=build_cell(cell,x,y,yl,hr)
47x+=wc}}
48line='<path class="stroke" d="\n'
49y=3
50for(i=0;i<=nr;i++){line+='M'+x0.toFixed(1)+' '+y.toFixed(1)+'h'+w.toFixed(1)+'\n'
51y+=hr}
52x=x0
53for(i=0;i<=nc;i++){line+='M'+x.toFixed(1)+' 3v'+(hr*nr).toFixed(1)+'\n'
54x+=wc}
55line+='"/>\n'
56line+=lc
57y=3-font.size*.7
58while(1){bl=bars.shift()
59if(!bl)
60break
61x=x0
62y+=hr
63while(1){bar=bl.shift()
64if(!bar)
65break
66if(bar[0]==':')
67line+='<text class="'+cls+'" x="'+
68(x-5).toFixed(1)+'" y="'+y.toFixed(1)+'" style="font-weight:bold;font-size:'+
69(font.size*1.6).toFixed(1)+'px">:</text>\n'
70if(bar.slice(-1)==':')
71line+='<text class="'+cls+'" x="'+
72(x+5).toFixed(1)+'" y="'+y.toFixed(1)+'" style="font-weight:bold;font-size:'+
73(font.size*1.6).toFixed(1)+'px">:</text>\n'
74x+=wc}}
75abc.out_svg(line)
76abc.vskip(hr*nr+6)}
77if(!cfmt.gridfont)
78abc.param_set_font("gridfont","serif 16")
79font=abc.get_font('grid')
80font_cl=abc.font_class(font)
81cls=font_cl+" mid"
82abc.add_style("\n.mid {text-anchor:middle}")
83abc.set_font('grid')
84txt=txt.split('\n')
85while(1){ln=txt.shift()
86if(!ln)
87break
88ln=ln.match(/[|:]+|[^|:\s]+/g)
89bars[nr]=[]
90cells[nr]=[]
91i=-1
92while(1){cl=ln.shift()
93if(!cl)
94break
95if(cl.match(/[:|]+/)){bars[nr][++i]=cl
96cells[nr][i]=[]}else{if(!cells[nr][i]){bars[nr][++i]='|'
97cells[nr][i]=[]}
98if(cl=='.'||cl=='-')
99cl=''
100cells[nr][i].push(cl)}}
101if(cells[nr][i].length)
102bars[nr][++i]='|'
103else
104cells[nr][i]=null
105if(i>nc)
106nc=i
107i=0
108while(1){cl=cells[nr][i++]
109if(!cl)
110break
111if(cl.length==2){cl[2]=cl[1]
112cl[1]=''}
113w=abc.strwh(cl.join(''))[0]
114if(w>wc)
115wc=w}
116nr++}
117wc+=abc.strwh('  ')[0]
118abc.blk_flush()
119build_grid()
120abc.blk_flush()},do_begin_end:function(of,type,opt,txt){var vt=this.get_voice_tb()
121if(type!="grid"){of(type,opt,txt)
122return}
123txt=txt.replace(/#|=|b/g,function(x){switch(x){case'#':return"\u266f"
124case'=':return"\u266e"}
125return"\u266d"})
126if(opt.indexOf("chord-define")>=0)
127this.cfmt().csdef=txt
128if(opt.indexOf("noprint")<0){if(this.parse.state>=2){s=this.new_block(type)
129s.text=txt}else{abc2svg.grid3.block_gen.call(this,null,{subtype:type,text:txt})}}},output_music:function(of){var ln,i,dt,ss,ntim,p_vc,s3,C=abc2svg.C,abc=this,s=abc.get_tsfirst(),vt=abc.get_voice_tb(),t=abc.cfmt().csdef,cs=[]
130function add_cs(ss,ch){var s={type:C.REST,fname:ss.fname,istart:ss.istart,iend:ss.iend,v:p_vc.v,p_v:p_vc,time:ntim,st:0,dur:0,dur_orig:0,invis:true,seqst:true,nhd:0,notes:[{pit:18,dur:0}]}
131if(ch!='.'&&ch!='-'){abc.set_a_gch(s,[{type:'g',text:ch,otext:ch,istart:ss.istart,iend:ss.iend,font:abc.get_font("gchord")}])}
132if(!p_vc.last_sym){p_vc.sym=s}else{s.prev=p_vc.last_sym
133s.prev.next=s}
134p_vc.last_sym=s
135s.ts_next=ss
136s.ts_prev=ss.ts_prev
137s.ts_prev.ts_next=s
138ss.ts_prev=s
139if(s.time==ss.time)
140delete ss.seqst
141return s}
142if(t){p_vc={id:"grid3",v:vt.length,time:0,pos:{gst:0},scale:1,st:0,second:true,sls:[]}
143vt.push(p_vc)
144t=t.split('\n')
145while(1){ln=t.shift()
146if(!ln)
147break
148ln=ln.trimLeft()
149if(ln[0]=='|')
150ln=ln.slice(ln[1]==':'?2:1)
151if(ln[ln.length-1]!='|')
152ln=ln+'|'
153ln=ln.match(/[|:]+|[^|:\s]+/g)
154while(1){cl=ln.shift()
155if(!cl)
156break
157if(cl[0]=='|'||cl[0]==':'){while(s&&!s.dur)
158s=s.ts_next
159if(!s)
160break
161ss=s
162while(s&&!s.bar_type)
163s=s.ts_next
164if(!cs.length)
165cs=['.']
166ntim=ss.time
167dt=(s.time-ntim)/cs.length
168s3=null
169for(i=0;i<cs.length;i++){if((cs[i]!='.'&&cs[i]!='-')||!s3){while(ss.time<ntim)
170ss=ss.ts_next
171s3=add_cs(ss,cs[i])}
172s3.dur+=dt
173s3.dur_orig=s3.notes[0].dur=s3.dur
174ntim+=dt}
175while(s&&s.type!=C.BAR)
176s=s.ts_next
177ss={type:C.BAR,bar_type:"|",fname:s.fname,istart:s.istart,iend:s.iend,v:p_vc.v,p_v:p_vc,st:0,time:s.time,dur:0,nhd:0,notes:[{pit:18}],next:s,ts_next:s,prev:s.prev,ts_prev:s.ts_prev}
178if(!s)
179break
180if(s.seqst){ss.seqst=true
181delete s.seqst}
182ss.prev.next=ss.ts_prev.ts_next=s.prev=s.ts_prev=ss
183cs=[]}else{cs.push(cl)}}}}
184of()},set_hooks:function(abc){abc.block_gen=abc2svg.grid3.block_gen.bind(abc,abc.block_gen)
185abc.do_begin_end=abc2svg.grid3.do_begin_end.bind(abc,abc.do_begin_end)
186abc.output_music=abc2svg.grid3.output_music.bind(abc,abc.output_music)}}
187abc2svg.modules.hooks.push(abc2svg.grid3.set_hooks)
188abc2svg.modules.begingrid.loaded=true
189