#! /bin/sh # "eps2otf" by Koichi Yasuoka, November 3, 2004 Registry=Adobe Ordering=Japan1 Supplement=6 FontBBox=0,-100,1000,900 Notice='Made with eps2otf written by Koichi Yasuoka.' FontName=temp$$font Version=1.0 TMP=/tmp/eps2otf$$ trap "rm -rf $TMP.* ; exit 2" 1 2 3 15 case "$1" in -*) if FontName=`expr "$1" : '-\([A-Za-z][^ ]*\)$'` then shift case "$1" in -*) if Version=`expr $1 : '-\([0-9][0-9]*\.[0-9][0-9]*\)$'` then shift else echo eps2otf: Version should be n.n >&2 exit 1 fi ;; esac else echo 'Usage: eps2otf [-FontName [-Version]] CID+UCS.eps ... | dir' >&2 exit 1 fi ;; esac if [ $# -eq 0 ] then echo 'Usage: eps2otf [-FontName [-Version]] CID+UCS.eps ... | dir' >&2 exit 1 fi cp /dev/null $TMP.cid mkdir $TMP.glyph ( if [ $# -eq 1 -a -d "$1" ] then find "$1" -name '[0-9]*+[0-9A-Fa-f]*.eps' -print else ls -1 $* fi ) | ( while read F do if expr "/$F" : '.*/[1-9][0-9]*+[0-9A-Fa-f][0-9A-Fa-f]*\.eps$' > /dev/null then if [ ! -f $F ] then echo $F not found >&2 continue fi else echo "$F" is not CID+UCS.eps >&2 continue fi cat - << 'EOF' > $TMP.ps %!PS-Adobe-1.0 /fill { gsave initmatrix (\n%%start%%\n) print { exch = = (moveto\n) print } { exch = = (lineto\n) print } { 6 packedarray {=} forall (curveto\n) print } { (closepath\n) print } pathforall (fill\n%%end%%\n) print grestore newpath } bind def /show { false charpath fill } bind def EOF awk ' BEGIN{ split("'$FontBBox'",b,","); } { if($1=="%%BoundingBox:"){ printf("%d %d translate\n",b[1],b[2]); printf("%d %s %s sub div %d %s %s sub div scale\n",b[3]-b[1],$4,$2,b[4]-b[2],$5,$3); printf("%s neg %s neg translate\n",$2,$3); } else printf("%s\n",$0); }' $F >> $TMP.ps echo quit | gs -DNODISPLAY $TMP.ps | sed -n ' /^%%start%%$/,/^%%end%%$/{ /%%/d :loop /[a-z]/{ p d } N s/\n/ / bloop } ' | sed ' :loop $q N s/^.* moveto\nclosepath$/closepath/ s/^.* moveto\nfill$/fill/ /\n/{ P D } bloop ' | awk ' BEGIN{ xx=yy=sx=sy=0; } { for(i=1;i=-107&&$i<=107) printf("%02x",$i+139); else if($i>=108&&$i<=1131) printf("%02x%02x",($i-108)/256+247,($i-108)%256); else if($i>=-1131&&$i<=-108) printf("%02x%02x",(-108-$i)/256+251,(-108-$i)%256); else printf("ff%04x0000",($i+65536)%65536); } if(c[$NF]>0) printf("%02x\n",c[$NF]); } ' > $TMP.glyph/`expr /$F : '.*/\([0-9]*\)+'` basename $F .eps | tr + ' ' >> $TMP.cid done ) set x `sort -n $TMP.cid | tail -1` if [ $# -eq 1 ] then echo 'Usage: eps2otf [-FontName [-Version]] CID+UCS.eps ... | dir' >&2 rm -rf $TMP.* exit 1 fi LASTCID=$2 echo 1 > $TMP.index find $TMP.glyph -type f -print | nawk ' { s=$1; sub(/^.*\.glyph\//,"",s); w[s]=$1; } END{ x=1; for(cid=0;cid<='$LASTCID';cid++){ if(w[cid]>""){ system("cat "w[cid]); c="wc "w[cid]; c|getline; close(c); x+=($3-$2)/2; } else{ printf("0e\n"); x++; } printf("%d\n",x)>>"'$TMP.index'"; } } ' > $TMP.glyphs awk ' BEGIN{ n=0; } { w[n++]=$1; } END{ printf("%04x\n",n-1); i=w[n-1]; if(i<256){ printf("01\n"); t="%02x\n"; } else if(i<65536){ printf("02\n"); t="%04x\n"; } else if(i<16777216){ printf("03\n"); t="%06x\n"; } else{ printf("04\n"); t="%08x\n"; } for(i=0;i $TMP.charstrings cat $TMP.glyphs >> $TMP.charstrings echo $FontName | awk ' { printf("00010101%02x\n",length($1)+1); for(i=33;i<127;i++) c[sprintf("%c",i)]=i; for(i=1;i<=length($1);i++) printf("%02x",c[substr($1,i,1)]); printf("\n"); } ' > $TMP.name ( echo $FontName-Internal echo $Registry echo $Ordering echo $Notice echo $FontName ) | awk ' BEGIN{ n[0]=1; } { w[NR]=$0; n[NR]=n[NR-1]+length($0); } END{ for(i=32;i<127;i++) c[sprintf("%c",i)]=i; printf("%04x\n",NR); i=n[NR]; if(i<256){ printf("01\n"); t="%02x\n"; } else if(i<65536){ printf("02\n"); t="%04x\n"; } else if(i<16777216){ printf("03\n"); t="%06x\n"; } else{ printf("04\n"); t="%08x\n"; } for(i=0;i<=NR;i++) printf(t,n[i]); for(i=1;i<=NR;i++){ for(j=1;j<=length(w[i]);j++) printf("%02x",c[substr(w[i],j,1)]); printf("\n"); } } ' > $TMP.string echo 0000 > $TMP.globalsubr echo $LASTCID | awk ' { printf("020001%04x\n",$1-1); } ' > $TMP.charset echo $LASTCID | awk ' { printf("030001000000%04x\n",$1+1); } ' > $TMP.fdselect echo 0001010105f81b0c26 > $TMP.fontdict echo 8b148b158b0c0a > $TMP.private echo 01000404 > $TMP.header cp /dev/null $TMP.topdict C=1 CFFSIZE=0 while [ $C -ne $CFFSIZE ] do C=$CFFSIZE wc $TMP.header $TMP.name $TMP.topdict $TMP.string $TMP.globalsubr $TMP.charset $TMP.fdselect $TMP.charstrings $TMP.fontdict $TMP.private | nawk ' BEGIN{ n=0; } { s=$4; sub(/^.*\./,"",s); t[s]=n; n+=w[s]=($3-$2)/2; } END{ printf("f81cf81d%s0c1e\n",num('$Supplement')); # ROS s="'$Version'ff"; if(length(s)%2==1) s=substr(s,1,length(s)-1); sub(/\./,"a",s); printf("1e%s0c1f\n",s); # CIDFontVersion printf("%s0c22\n",num('$LASTCID'+1)); # CIDCount printf("f81e01\n"); # Notice printf("f81f02\n"); # FullName printf("f81f03\n"); # FamilyName printf("f81804\n"); # Weight split("'$FontBBox'",b,","); printf("%s%s%s%s05\n",num(b[1]),num(b[2]),num(b[3]),num(b[4])); # FontBBox printf("%s0f\n",num(t["charset"])); # charset printf("%s0c25\n",num(t["fdselect"])); # FDSelect printf("%s11\n",num(t["charstrings"])); # CharStrings printf("%s0c24\n",num(t["fontdict"])); # FDArray s=sprintf("%s14%s15%s0c0a",num(b[4]),num(0),num(0)); printf("%s\n",s)>"'$TMP.private'"; s=sprintf("f81b0c26%s%s12",num(length(s)/2),num(t["private"])); printf("00010101%02x%s\n",length(s)/2+1,s)>"'$TMP.fontdict'"; } function num(x){ if(x>=-107&&x<=107) return(sprintf("%02x",x+139)); if(x>=108&&x<=1131) return(sprintf("%02x%02x",(x-108)/256+247,(x-108)%256)); if(x>=-1131&&x<=-108) return(sprintf("02x%02x",(-108-x)/256+251,(-108-x)%256)); if(x>=-32768&&x<=32767) return(sprintf("1c%04x",x)); return(sprintf("1d%08x",x)); } ' > $TMP.dict wc $TMP.dict | awk ' { i=($3-$2)/2+1; if(i<256) printf("00010101%02x\n",i); else printf("0001020001%04x\n",i); } ' > $TMP.dictindex cat $TMP.dictindex $TMP.dict > $TMP.topdict set `wc $TMP.header $TMP.name $TMP.topdict $TMP.string $TMP.globalsubr $TMP.charset $TMP.fdselect $TMP.charstrings $TMP.fontdict $TMP.private | tail -1` CFFSIZE=`expr '(' $3 - $2 ')' / 2` done if [ $CFFSIZE -lt 65536 ] then echo 01000402 > $TMP.header elif [ $CFFSIZE -lt 16777216 ] then echo 01000403 > $TMP.header else echo 01000404 > $TMP.header fi cat $TMP.header $TMP.name $TMP.topdict $TMP.string $TMP.globalsubr $TMP.charset $TMP.fdselect $TMP.charstrings $TMP.fontdict $TMP.private > $TMP.cff sed ' y/ABCDEF/abcdef/ s/^\(.*\) \(.*\)$/0000000\2 0000\1/ s/^0*\(........\) 0*\(.....\)$/\1 \2/ ' $TMP.cid | sort | sed ' :loop $q N s/^\([^ ]* \).*\n\1/\1/ /\n/{ P D } bloop ' | tee $TMP.ucs4 | egrep '^0000' > $TMP.ucs2 set x `tail -1 $TMP.ucs2` if [ "$2" != 0000ffff ] then echo 0000ffff 00000 >> $TMP.ucs2 fi wc $TMP.ucs2 | awk ' { printf("0004\n"); printf("%04x\n",$1*8+16); printf("0000\n"); s=-1; for(r=1;r<=$1;r*=2) s++; printf("%04x\n%04x\n%04x\n%04x\n",$1*2,r,s,$1*2-r); } ' > $TMP.cmap4 sed 's/^0000\(....\) .*$/\1/' $TMP.ucs2 >> $TMP.cmap4 echo 0000 >> $TMP.cmap4 sed 's/^0000\(....\) .*$/\1/' $TMP.ucs2 >> $TMP.cmap4 ( echo 16 o sed ' y/abcdef/ABCDEF/ s/^\(.*\) \(.*\)$/A i \2 16 i \1 - 20000 + p s./ ' $TMP.ucs2 echo q ) | dc | sed ' s/^.// y/ABCDEF/abcdef/ ' >> $TMP.cmap4 sed 's/^.*$/0000/' $TMP.ucs2 >> $TMP.cmap4 wc $TMP.ucs4 | awk ' { printf("000c\n"); printf("0000\n"); printf("%08x\n",$1*12+16); printf("00000000\n"); printf("%08x\n",$1); } ' > $TMP.cmap12 awk ' { printf("%s\n",$1); printf("%s\n",$1); printf("%08x\n",$2); } ' $TMP.ucs4 >> $TMP.cmap12 wc $TMP.cmap4 | nawk ' { printf("0000\n"); printf("0003\n"); printf("0000\n0003\n0000001c\n"); printf("0003\n0001\n0000001c\n"); printf("0003\n000a\n%08x\n",($3-$2)/2+28); } ' > $TMP.cmap cat $TMP.cmap4 $TMP.cmap12 >> $TMP.cmap cat << 'EOF' > $TMP.head 00010000 00010000 00000000 5f0f3cf5 0003 03e8 EOF date -u +'%Y 1904 - sa la 365 * la 3 + 4 / + %j + 24 * %H + 60 * %M + 60 * %S + 16 o p q' | dc | sed ' y/ABCDEF/abcdef/ s/^/000000000000000/ s/^0*\(................\)$/\1/ p ' >> $TMP.head echo $FontBBox | awk -F, ' { for(i=1;i<5;i++) printf("%04x\n",($i+65536)%65536); printf("0000\n"); printf("0003\n"); printf("0002\n"); printf("0000\n"); printf("0000\n"); } ' >> $TMP.head echo $LASTCID | awk ' { printf("00005000\n"); printf("%04x\n",$1+1); } ' > $TMP.maxp set `wc $TMP.ucs2` echo $FontBBox | awk -F, ' { printf("00010000\n"); printf("%04x\n",$4); printf("%04x\n",($2+65536)%65536); printf("%04x\n",$4-$2); printf("%04x\n",$3); printf("%04x\n",($1+65536)%65536); printf("0000\n"); printf("%04x\n",$3-$1); printf("0001\n"); printf("0000\n"); printf("0000\n"); printf("0000\n0000\n0000\n0000\n"); printf("0000\n"); printf("0002\n"); } ' > $TMP.hhea echo $FontBBox | awk -F, ' { for(i=0;i<2;i++) printf("%04x\n0000\n",$3); for(i=2;i<='$LASTCID';i++) printf("0000\n"); } ' > $TMP.hmtx echo $FontBBox | awk -F, ' { printf("0002\n"); # version printf("%04x\n",$3); # xAvgCharWidth printf("0190\n"); # usWeightClass printf("0005\n"); # usWidthClass printf("0000\n"); # fsType printf("%04x\n",($3-$1)/2); # ySubscriptXsize printf("%04x\n",($4-$2)/2); # ySubscriptYsize printf("0000\n"); # ySubscriptXOffset printf("0000\n"); # ySubscriptYOffset printf("%04x\n",($3-$1)/2); # ySuperscriptXsize printf("%04x\n",($4-$2)/2); # ySuperscriptYsize printf("0000\n"); # ySuperscriptXOffset printf("%04x\n",$4/2); # ySuperscriptYOffset printf("0032\n"); # yStrikeoutSize printf("%04x\n",($2+$4)/2); # yStrikeoutPosition printf("0000\n"); # sFamilyClass printf("02040400000000000000\n"); # Panose printf("800002df68c7fcff0000001d00000000\n"); # ulUnicodeRange printf("20202020\n"); # achVendID printf("0040\n"); # fsSelection printf("0000\n"); # usFirstCharIndex printf("ffff\n"); # usLastCharIndex printf("%04x\n",$4); # sTypoAscender printf("%04x\n",($2+65536)%65536); # sTypoDescender printf("%04x\n",$4-$2); # sTypoLineGap printf("%04x\n",$4); # usWinAscent printf("%04x\n",(65536-$2)%65536); # usWinDescent printf("0002000d00000000\n"); # ulCodePageRange printf("0000\n"); # sxHeight printf("0000\n"); # sCapHeight printf("0000\n"); # usDefaultChar printf("0000\n"); # usBreakChar printf("0008\n"); # usMaxContext } ' > $TMP.os2 echo $FontBBox | awk -F, ' { printf("00030000\n"); printf("00000000\n"); printf("%04x\n",($2+65486)%65536); printf("0032\n"); printf("00000000\n"); printf("00000000\n"); printf("00000000\n"); printf("00000000\n"); printf("00000000\n"); } ' > $TMP.post ( echo $Notice echo $FontName echo Regular echo $FontName echo $FontName echo $Version echo $FontName echo No Trademark. id | tr '\012' ' ' ; uname -a ) | nawk ' BEGIN{ for(i=32;i<127;i++) c[sprintf("%c",i)]=i; n=x=0; } { printf("000100000000%04x%04x%04x\n",n,length($0),x)>"'$TMP.name.index'"; for(i=1;i<=length($0);i++) printf("%02x",c[substr($0,i,1)]); printf("\n"); x+=length($0); printf("000300010409%04x%04x%04x\n",n,length($0)*2,x)>"'$TMP.name.index'"; for(i=1;i<=length($0);i++) printf("%04x",c[substr($0,i,1)]); printf("\n"); x+=length($0)*2; n++; } ' > $TMP.name.body wc $TMP.name.index | awk ' { printf("0000\n"); printf("%04x\n",$1); printf("%04x\n",($3-$2)/2+6); } ' > $TMP.name.head cat $TMP.name.head $TMP.name.index $TMP.name.body > $TMP.name cp /dev/null $TMP.tables for F in head hhea maxp os2 name cff cmap hmtx post do case $F in cff) N='CFF ' ;; os2) N=OS/2 ;; *) N=$F ;; esac echo "$N" | tr '\012' ' ' >> $TMP.tables awk ' BEGIN{ n=0 printf("16 o 16 i 0\n"); } { for(i=1;i<=NF;i++){ for(j=1;j<=length($i);j+=2){ printf("%s",substr($i,j,2)); n++; if(n%4==0) printf(" +\n"); } } } END{ if(n%4!=0){ for(i=n;i%4!=0;i++) printf("00"); printf(" +\n"); } printf("100000000 %% p %x p q\n",n); } ' $TMP.$F | tr abcdef ABCDEF | dc | tr '\012' ' ' >> $TMP.tables echo $TMP.$F >> $TMP.tables done awk ' BEGIN{ for(i=32;i<127;i++) c[sprintf("%c",i)]=i; } { for(i=1;i<5;i++) printf("%02x",c[substr($0,i,1)]); printf("\n"); } ' $TMP.tables > $TMP.table.tag join -o 1.2 -a1 $TMP.tables /dev/null | sed ' y/ABCDEF/abcdef/ s/^/0000000/ s/^0*\(........\)/\1/ ' > $TMP.table.checksum set `wc $TMP.tables` ( expr $1 '*' 16 + 12 echo 16 o 16 i p join -o 1.3 -a1 $TMP.tables /dev/null | sed ' $d s/$/ + 3 + 4 \/ 4 * p/ ' echo q ) | dc | sed ' y/ABCDEF/abcdef/ s/^/0000000/ s/^0*\(........\)/\1/ ' > $TMP.table.offset join -o 1.3 -a1 $TMP.tables /dev/null | sed ' y/ABCDEF/abcdef/ s/^/0000000/ s/^0*\(........\)/\1/ ' > $TMP.table.length wc $TMP.tables | awk ' { printf("4f54544f\n"); i=-1; for(r=1;r<=$1;r*=2) i++; r*=8; printf("%04x\n%04x\n%04x\n%04x\n",$1,r,i,$1*16-r); } ' > $TMP.directory paste $TMP.table.tag $TMP.table.checksum $TMP.table.offset $TMP.table.length | sed 's/[^0-9a-f]//g' | sort >> $TMP.directory ( echo 16 o 16 i 1B1B0AFBA 0 awk ' BEGIN{ n=0 } { for(i=1;i<=NF;i++){ for(j=1;j<=length($i);j+=2){ printf("%s",substr($i,j,2)); n++; if(n%4==0) printf(" +\n"); } } } END{ if(n%4!=0){ for(i=n;i%4!=0;i++) printf("00"); printf(" +\n"); } } ' $TMP.directory | tr abcdef ABCDEF sed ' y/abcdef/ABCDEF/ s/$/ +/ ' $TMP.table.checksum echo 100000000 % - 100000000 % p q ) | dc | sed ' y/ABCDEF/abcdef/ s/^/0000000/ s/^0*\(........\)$/3s\/00000000\/\1\// p s/^.*$/w/ p s/^.*$/q/ ' | ed $TMP.head > /dev/null 2>&1 ( echo begin 644 $TMP.output for F in $TMP.directory `join -o 1.4 -a1 $TMP.tables /dev/null` do awk ' BEGIN{ for(i=0;i<256;i++) u[sprintf("%02x",i)]=sprintf("!%c%c ",i/4+32,i%4*16+32); n=0; } { for(i=1;i<=NF;i++){ for(j=1;j<=length($i);j+=2){ printf("%s\n",u[substr($i,j,2)]); n++; } } } END{ while(n%4!=0){ printf("%s\n",u["00"]); n++; } } ' $F done echo ' ' echo end ) | uudecode cat $TMP.output rm -rf $TMP.* exit 0