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//page.js-module to generate pages
5abc2svg.page={img_out:function(page,p){var cur_img_out=user.img_out;page.user_out(p)
6if(user.img_out!=cur_img_out){page.user_out=user.img_out
7user.img_out=cur_img_out}},abc_end:function(of){var page=this.page
8if(page&&page.in_page){abc2svg.page.close_page(page)
9if(user.img_out==page.img_out_sav)
10user.img_out=page.user_out}
11of()},gen_hf:function(page,ty){var a,i,j,k,x,y,y0,s,font=page.abc.get_font(ty),str=page[ty],cfmt=page.abc.cfmt(),fh=font.size*1.1,pos=['">','" text-anchor="middle">','" text-anchor="end">']
12function header_footer(o_font,str){var c,i,k,t,n_font,c_font=o_font,nl=1,j=0,r=["","",""]
13if(str[0]=='"')
14str=str.slice(1,-1)
15if(str.indexOf('\t')<0)
16str='\t'+str
17for(i=0;i<str.length;i++){c=str[i]
18switch(c){case'>':r[j]+="&gt;"
19continue
20case'<':r[j]+="&lt;"
21continue
22case'&':for(k=i+1;k<i+8;k++){if(!str[k]||str[k]=='&'||str[k]==';')
23break}
24r[j]+=str[k]==';'?"&":"&amp;"
25continue
26case'\t':if(j<2)
27j++
28continue
29case'\\':if(c_font!=o_font){r[j]+="</tspan>"}
30for(j=0;j<3;j++)
31r[j]+='\n';nl++;j=0;i++
32continue
33default:r[j]+=c
34continue
35case'$':break}
36c=str[++i]
37switch(c){case'd':if(!abc2svg.get_mtime)
38break
39t=abc2svg.get_mtime(page.abc.parse.fname)
40case'D':if(c=='D')
41t=new Date()
42if(cfmt.dateformat[0]=='"')
43cfmt.dateformat=cfmt.dateformat.slice(1,-1)
44r[j]+=strftime(cfmt.dateformat,t)
45break
46case'F':r[j]+=page.abc.parse.fname
47break
48case'I':c=str[++i]
49case'T':t=page.abc.info()[c]
50if(t)
51r[j]+=t.split('\n',1)[0]
52break
53case'P':case'Q':t=c=='P'?page.pn:page.pna
54switch(str[i+1]){case'0':i++
55if(!(t&1))
56r[j]+=t
57break
58case'1':i++
59if(t&1)
60r[j]+=t
61break
62default:r[j]+=t
63break}
64break
65case'V':r[j]+="abc2svg-"+abc2svg.version
66break
67default:if(c=='0')
68n_font=o_font
69else if(c>='1'&&c<'9')
70n_font=page.abc.get_font("u"+c)
71else
72break
73if(n_font==c_font)
74break
75if(c_font!=o_font)
76r[j]+="</tspan>";c_font=n_font
77if(c_font==o_font)
78break
79r[j]+='<tspan class="'+
80font_class(n_font)+'">'
81break}}
82if(c_font!=o_font)
83r[j]+="</tspan>";r[4]=nl
84return r}
85function font_class(font){if(font.class)
86return'f'+font.fid+cfmt.fullsvg+' '+font.class
87return'f'+font.fid+cfmt.fullsvg}
88if(str[0]=='-'){if(page.pn==1)
89return 0
90str=str.slice(1)}
91a=header_footer(font,str)
92y0=font.size*.8
93for(i=0;i<3;i++){str=a[i]
94if(!str)
95continue
96if(i==0)
97x=cfmt.leftmargin
98else if(i==1)
99x=cfmt.pagewidth/2
100else
101x=cfmt.pagewidth-cfmt.rightmargin
102y=y0
103k=0
104while(1){j=str.indexOf('\n',k)
105if(j>=0)
106s=str.slice(k,j)
107else
108s=str.slice(k)
109if(s)
110page.hf+='<text class="'+
111font_class(font)+'" x="'+x.toFixed(1)+'" y="'+y.toFixed(1)+
112pos[i]+
113s+'</text>\n'
114if(j<0)
115break
116k=j+1
117y+=fh}}
118return fh*a[4]},open_page:function(page,ht){var h,l,abc=page.abc,cfmt=abc.cfmt(),sty='<div style="line-height:0'
119page.pn++
120page.pna++
121if(page.first)
122page.first=false
123else
124sty+=";page-break-before:always"
125if(page.gutter)
126sty+=";margin-left:"+
127((page.pn&1)?page.gutter:-page.gutter).toFixed(1)+"px"
128abc2svg.page.img_out(page,sty+'">')
129page.in_page=true
130ht+=page.topmargin
131page.hmax=cfmt.pageheight-page.botmargin-ht
132page.hf=''
133if(page.header){l=abc.get_font_style().length
134h=abc2svg.page.gen_hf(page,"header")
135sty=abc.get_font_style().slice(l)
136if(cfmt.fullsvg||sty!=page.hsty){page.hsty=sty
137sty='<style>'+sty+'\n</style>\n'}else{sty=''}
138abc2svg.page.img_out(page,'<svg xmlns="http://www.w3.org/2000/svg" version="1.1"\n\
139 xmlns:xlink="http://www.w3.org/1999/xlink"\n\
140 width="'+cfmt.pagewidth.toFixed(0)+'px" height="'+(ht+h).toFixed(0)+'px">\n'+sty+'<g transform="translate(0,'+
141page.topmargin.toFixed(1)+')">'+
142page.hf+'</g>\n</svg>')
143page.hmax-=h;page.hf=''}else{abc2svg.page.img_out(page,'<svg xmlns="http://www.w3.org/2000/svg" version="1.1"\n\
144 xmlns:xlink="http://www.w3.org/1999/xlink"\n\
145 width="'+cfmt.pagewidth.toFixed(0)+'px" height="'+ht.toFixed(0)+'px">\n</svg>')}
146if(page.footer){l=abc.get_font_style().length
147page.fh=abc2svg.page.gen_hf(page,"footer")
148sty=abc.get_font_style().slice(l)
149if(cfmt.fullsvg||sty!=page.fsty){page.fsty=sty
150page.ffsty='<style>'+sty+'\n</style>\n'}else{page.ffsty=''}
151page.hmax-=page.fh}
152page.h=0},close_page:function(page){var h,cfmt=page.abc.cfmt()
153page.in_page=false
154if(page.footer){h=page.hmax+page.fh-page.h
155abc2svg.page.img_out(page,'<svg xmlns="http://www.w3.org/2000/svg" version="1.1"\n\
156 xmlns:xlink="http://www.w3.org/1999/xlink"\n\
157 width="'+cfmt.pagewidth.toFixed(0)+'px" height="'+h.toFixed(0)+'px">\n'+page.ffsty+'<g transform="translate(0,'+
158(h-page.fh).toFixed(1)+')">'+
159page.hf+'</g>\n</svg>')}
160abc2svg.page.img_out(page,'</div>')
161page.h=0},img_in:function(p){var h,ht,nh,page=this.page
162function blkcpy(page){while(page.blk.length)
163abc2svg.page.img_out(page,page.blk.shift())
164page.blk=null}
165switch(p.slice(0,4)){case"<div":if(p.indexOf('newpage')>0||(page.oneperpage&&this.info().X)||!page.h){if(page.in_page)
166abc2svg.page.close_page(page)
167abc2svg.page.open_page(page,0)}
168page.blk=[]
169page.hb=page.h
170break
171case"<svg":h=Number(p.match(/height="(\d+)px"/)[1])
172while(h+page.h>=page.hmax){ht=page.blk?0:this.cfmt().topspace
173if(page.blk){if(!page.hb){blkcpy(page)
174nh=0}else{nh=page.h-page.hb
175page.h=page.hb}}
176abc2svg.page.close_page(page)
177abc2svg.page.open_page(page,ht)
178if(page.blk){blkcpy(page)
179page.h=nh}
180if(h>page.hmax)
181break}
182if(page.blk)
183page.blk.push(p)
184else
185abc2svg.page.img_out(page,p)
186page.h+=h
187break
188case"</di":if(page.blk)
189blkcpy(page)
190break}},set_fmt:function(of,cmd,parm){var v,cfmt=this.cfmt(),page=this.page
191if(cmd=="pageheight"){v=this.get_unit(parm)
192if(isNaN(v)){this.syntax(1,this.errs.bad_val,'%%'+cmd)
193return}
194cfmt.pageheight=v
195if(!page&&user.img_out&&abc2svg.abc_end){this.page=page={abc:this,topmargin:38,botmargin:38,h:0,pn:0,pna:0,first:true,user_out:user.img_out}
196if(cfmt.header){page.header=cfmt.header;cfmt.header=null}
197if(cfmt.footer){page.footer=cfmt.footer;cfmt.footer=null}
198if(cfmt.botmargin!=undefined){v=this.get_unit(cfmt.botmargin)
199if(!isNaN(v))
200page.botmargin=v}
201if(cfmt.topmargin!=undefined){v=this.get_unit(cfmt.topmargin)
202if(!isNaN(v))
203page.topmargin=v}
204if(cfmt.gutter!=undefined){v=this.get_unit(cfmt.gutter)
205if(!isNaN(v))
206page.gutter=v}
207if(cfmt.oneperpage)
208page.oneperpage=this.get_bool(cfmt.oneperpage)
209if(!cfmt.dateformat)
210cfmt.dateformat="%b %e, %Y %H:%M"
211user.img_out=abc2svg.page.img_in.bind(this);page.img_out_sav=user.img_out;abc2svg.abc_end=abc2svg.page.abc_end.bind(this,abc2svg.abc_end)}
212return}
213if(page){switch(cmd){case"header":case"footer":page[cmd]=parm
214return
215case"newpage":if(!parm)
216break
217v=Number(parm)
218if(isNaN(v)){this.syntax(1,this.errs.bad_val,'%%'+cmd)
219return}
220page.pn=v-1
221return
222case"gutter":case"botmargin":case"topmargin":v=this.get_unit(parm)
223if(isNaN(v)){this.syntax(1,this.errs.bad_val,'%%'+cmd)
224return}
225page[cmd]=v
226return
227case"oneperpage":page[cmd]=this.get_bool(parm)
228return}}
229of(cmd,parm)},set_hooks:function(abc){abc.set_format=abc2svg.page.set_fmt.bind(abc,abc.set_format)
230user.page_format=true
231abc.set_pagef()}}
232abc2svg.modules.hooks.push(abc2svg.page.set_hooks);abc2svg.modules.pageheight.loaded=true
233function strftime(sFormat,date){if(!(date instanceof Date))date=new Date();var nDay=date.getDay(),nDate=date.getDate(),nMonth=date.getMonth(),nYear=date.getFullYear(),nHour=date.getHours(),aDays=['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],aMonths=['January','February','March','April','May','June','July','August','September','October','November','December'],aDayCount=[0,31,59,90,120,151,181,212,243,273,304,334],isLeapYear=function(){return(nYear%4===0&&nYear%100!==0)||nYear%400===0},getThursday=function(){var target=new Date(date);target.setDate(nDate-((nDay+6)%7)+3);return target},zeroPad=function(nNum,nPad){return((Math.pow(10,nPad)+nNum)+'').slice(1)};return sFormat.replace(/%[a-z]/gi,function(sMatch){return(({'%a':aDays[nDay].slice(0,3),'%A':aDays[nDay],'%b':aMonths[nMonth].slice(0,3),'%B':aMonths[nMonth],'%c':date.toUTCString(),'%C':Math.floor(nYear/100),'%d':zeroPad(nDate,2),'%e':nDate,'%F':date.toISOString().slice(0,10),'%G':getThursday().getFullYear(),'%g':(getThursday().getFullYear()+'').slice(2),'%H':zeroPad(nHour,2),'%I':zeroPad((nHour+11)%12+1,2),'%j':zeroPad(aDayCount[nMonth]+nDate+((nMonth>1&&isLeapYear())?1:0),3),'%k':nHour,'%l':(nHour+11)%12+1,'%m':zeroPad(nMonth+1,2),'%n':nMonth+1,'%M':zeroPad(date.getMinutes(),2),'%p':(nHour<12)?'AM':'PM','%P':(nHour<12)?'am':'pm','%s':Math.round(date.getTime()/1000),'%S':zeroPad(date.getSeconds(),2),'%u':nDay||7,'%V':(function(){var target=getThursday(),n1stThu=target.valueOf();target.setMonth(0,1);var nJan1=target.getDay();if(nJan1!==4)target.setMonth(0,1+((4-nJan1)+7)%7);return zeroPad(1+Math.ceil((n1stThu-target)/604800000),2)})(),'%w':nDay,'%x':date.toLocaleDateString(),'%X':date.toLocaleTimeString(),'%y':(nYear+'').slice(2),'%Y':nYear,'%z':date.toTimeString().replace(/.+GMT([+-]\d+).+/,'$1'),'%Z':date.toTimeString().replace(/.+\((.+?)\)$/,'$1')}[sMatch]||'')+'')||sMatch})}
234