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]+=">" 19continue 20case'<':r[j]+="<" 21continue 22case'&':for(k=i+1;k<i+8;k++){if(!str[k]||str[k]=='&'||str[k]==';') 23break} 24r[j]+=str[k]==';'?"&":"&" 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