% a font devised for typesetting certain "Celtic paths" % (see program CELTIC-PATHS for more details) % --- Don Knuth, August 2010 mode_setup; quad#:=13u#; define_pixels(u,d); font_size 13u#; pickup pencircle scaled d; thick_pen=savepen; numeric s; s=1.5u*sqrt2; z0l=(s,13u); z0=(0,13u); z0r=(0,13u-s); z1l=(8u,13u); z1=(6.5u,13u); z1r=(5u,13u); z2l=(13u,13u-s); z2=(13u,13u); z2r=(13u-s,13u); z3l=(13u,5u); z3=(13u,6.5u); z3r=(13u,8u); z4l=(13u-s,0); z4=(13u,0); z4r=(13u,s); z5l=(5u,0); z5=(6.5u,0); z5r=(8u,0); z6l=(0,s); z6=(0,0); z6r=(s,0); z7l=(0,8u); z7=(0,6.5u); z7r=(0,5u); z10=dir -45; z11=down; z12=dir -135; z13=left; z14=dir 135; z15=up; z16=dir 45; z17=right; path p[][]; for i=0 upto 7: for j=0 upto 7: if i<>j: if (i-j) mod 8 <> 1: if (j-i) mod 8 <> 1: if (i mod 2 = 1) or (j mod 2 = 1): p[i][j]=z[i]l{z[i+10]}...z[j]r{-z[j+10]}; fi fi fi fi endfor endfor path p[][]l; for j=0 step 2 until 6: p[j][(j+3)mod 8]l=p[j][(j+3)mod 8]--z[(j+2)mod 8]--cycle; p[j][(j+5)mod 8]l=p[j][(j+5)mod 8]--z[(j+4)mod 8]--z[(j+2)mod 8]--cycle; p[j+1][(j+3)mod 8]l=p[j+1][(j+3)mod 8]--z[(j+2)mod 8]--cycle; p[j+1][(j+4)mod 8]l=p[j+1][(j+4)mod 8]--z[(j+2)mod 8]--cycle; p[j+1][(j+5)mod 8]l=p[j+1][(j+5)mod 8]--z[(j+4)mod 8]--z[(j+2)mod 8]--cycle; p[j+1][(j+6)mod 8]l=p[j+1][(j+6)mod 8]--z[(j+4)mod 8]--z[(j+2)mod 8]--cycle; p[j+1][(j+7)mod 8]l=p[j+1][(j+7)mod 8]--z[(j+6)mod 8] --z[(j+4)mod 8]--z[(j+2)mod 8]--cycle; endfor def filland(expr p,q) = begingroup picture regp,regq; regp:=nullpicture; addto regp contour p; addto regp doublepath p withpen currentpen; cull regp keeping (1,infinity); %display regp inwindow currentwindow; errmessage "regp"; regq:=nullpicture; addto regq contour q; addto regq doublepath q withpen currentpen; cull regq keeping (1,infinity); %display regq inwindow currentwindow; errmessage "regq"; addto regp also regq; %display regp inwindow currentwindow; errmessage "regp"; cull regp keeping (2,2); %display regp inwindow currentwindow; errmessage "regp"; addto currentpicture also regp; endgroup enddef; def begincchar(expr c) = beginchar(c,quad#,quad#,0); pickup thick_pen; z0l=(s,13u); z0=(0,13u); z0r=(0,13u-s); z1l=(8u,13u); z1=(6.5u,13u); z1r=(5u,13u); z2l=(13u,13u-s); z2=(13u,13u); z2r=(13u-s,13u); z3l=(13u,5u); z3=(13u,6.5u); z3r=(13u,8u); z4l=(13u-s,0); z4=(13u,0); z4r=(13u,s); z5l=(5u,0); z5=(6.5u,0); z5r=(8u,0); z6l=(0,s); z6=(0,0); z6r=(s,0); z7l=(0,8u); z7=(0,6.5u); z7r=(0,5u); z10=dir -45; z11=down; z12=dir -135; z13=left; z14=dir 135; z15=up; z16=dir 45; z17=right; enddef; boolean charstopping; charstopping:=false; def endcchar = if charstopping: showit; errmessage decimal charcode; fi endchar; enddef; begincchar(oct"40"); fill z0--z2--z4--z6--cycle; draw z0--z2--z4--z6--cycle; endcchar; def singlechar(expr c,i,j) = % "white" is on left of p[i][j] begincchar(c); draw p[i][j]l; fill p[i][j]l; draw p[j][i]l; fill p[j][i]l; if j mod 2 = 0: draw z[j]l--z[j]r; fi endcchar; begincchar(c+1); draw p[i][j]; filldraw p[j][i]l; if j mod 2 = 0: draw z[j]l--z[j]r; fi endcchar; enddef; singlechar(oct"44",0,3); singlechar(oct"46",0,5); singlechar(oct"50",3,1); singlechar(oct"52",4,1); singlechar(oct"54",5,1); singlechar(oct"56",6,1); singlechar(oct"60",7,1); singlechar(oct"62",5,2); singlechar(oct"64",7,2); singlechar(oct"66",5,3); singlechar(oct"70",6,3); singlechar(oct"72",7,3); singlechar(oct"74",7,4); singlechar(oct"76",7,5); def doublecharwbw(expr c,i,j,ii,jj) = % two arcs, no overlap, middle black begincchar(c); fill p[i][j]l; draw p[i][j]l; filland(p[j][i]l,p[jj][ii]l); fill p[ii][jj]l; draw p[ii][jj]l; if j mod 2 = 0: draw z[j]l--z[j]r; fi if jj mod 2 = 0: draw z[jj]l--z[jj]r; fi endcchar; begincchar(c+1); draw p[i][j]; filland(p[j][i]l,p[jj][ii]l); fill p[ii][jj]l; draw p[ii][jj]l; if j mod 2 = 0: draw z[j]l--z[j]r; fi if jj mod 2 = 0: draw z[jj]l--z[jj]r; fi endcchar; begincchar(c+2); fill p[i][j]l; draw p[i][j]l; filland(p[j][i]l,p[jj][ii]l); draw p[ii][jj]; if j mod 2 = 0: draw z[j]l--z[j]r; fi if jj mod 2 = 0: draw z[jj]l--z[jj]r; fi endcchar; begincchar(c+3); draw p[i][j]; filland(p[j][i]l,p[jj][ii]l); draw p[ii][jj]; if j mod 2 = 0: draw z[j]l--z[j]r; fi if jj mod 2 = 0: draw z[jj]l--z[jj]r; fi endcchar; enddef; def doublecharbwb(expr c,i,j,ii,jj) = % two arcs, no overlap, middle white begincchar(c); draw p[j][i]l; fill p[j][i]l; filland(p[i][j]l,p[ii][jj]l); draw p[jj][ii]l; fill p[jj][ii]l; if j mod 2 = 0: draw z[j]l--z[j]r; fi if jj mod 2 = 0: draw z[jj]l--z[jj]r; fi endcchar; begincchar(c+3); draw p[j][i]l; fill p[j][i]l; draw p[i][j]; draw p[ii][jj]; draw p[jj][ii]l; fill p[jj][ii]l; if j mod 2 = 0: draw z[j]l--z[j]r; fi if jj mod 2 = 0: draw z[jj]l--z[jj]r; fi endcchar; enddef; doublecharbwb(oct"100",3,1,7,5); doublecharwbw(oct"104",7,1,3,5); doublecharbwb(oct"110",0,5,3,1); doublecharwbw(oct"114",7,2,3,5); doublecharbwb(oct"120",4,1,7,5); doublecharwbw(oct"124",7,1,3,6); doublecharwbw(oct"130",0,3,5,7); doublecharwbw(oct"134",7,1,2,5); doublecharbwb(oct"140",3,1,7,4); doublecharwbw(oct"144",6,1,3,5); doublecharbwb(oct"150",0,5,3,1); doublecharwbw(oct"154",7,2,3,6); doublecharwbw(oct"160",0,3,4,7); doublecharwbw(oct"164",6,1,2,5); path cuttings; % what got cut off tertiarydef a cutbefore b = % tries to cut as little as possible begingroup save t; (t, whatever) = a intersectiontimes b; if t<0: cuttings:=point 0 of a; a else: cuttings:= subpath (0,t) of a; subpath (t,length a) of a fi endgroup enddef; tertiarydef a cutafter b = reverse (reverse a cutbefore b) hide(cuttings:=reverse cuttings) enddef; def doublechar(expr c,i,j,ii,jj) = % i j under ii jj; (i ii j jj) ctrclkwise begincchar(c); filland(p[i][j]l,p[jj][ii]l); filland(p[i][j]l,p[ii][jj]l); filland(p[j][i]l,p[jj][ii]l); filland(p[j][i]l,p[ii][jj]l); draw p[ii][jj]; draw p[jj][ii]; if ii mod 2 = 0: draw z[ii]l--z[ii]r; fi if jj mod 2 = 0: draw z[jj]l--z[jj]r; fi endcchar; begincchar(c+1); draw p[i][j] cutafter p[jj][ii]; filland(p[i][j]l,p[ii][jj]l); filland(p[j][i]l,p[jj][ii]l); filland(p[j][i]l,p[ii][jj]l); draw p[ii][jj]; draw p[jj][ii]; if ii mod 2 = 0: draw z[ii]l--z[ii]r; fi if jj mod 2 = 0: draw z[jj]l--z[jj]r; fi endcchar; begincchar(c+2); filland(p[i][j]l,p[jj][ii]l); filland(p[i][j]l,p[ii][jj]l); filland(p[j][i]l,p[jj][ii]l); draw p[j][i] cutafter p[ii][jj]; draw p[ii][jj]; draw p[jj][ii]; if ii mod 2 = 0: draw z[ii]l--z[ii]r; fi if jj mod 2 = 0: draw z[jj]l--z[jj]r; fi endcchar; begincchar(c+3); draw p[i][j] cutafter p[jj][ii]; filland(p[i][j]l,p[ii][jj]l); filland(p[j][i]l,p[jj][ii]l); draw p[j][i] cutafter p[ii][jj]; draw p[ii][jj]; draw p[jj][ii]; if ii mod 2 = 0: draw z[ii]l--z[ii]r; fi if jj mod 2 = 0: draw z[jj]l--z[jj]r; fi endcchar; enddef; doublechar(oct"170",0,3,1,4); doublechar(oct"174",6,3,2,5); doublechar(oct"200",0,5,4,7); doublechar(oct"204",7,2,1,6); doublechar(oct"210",0,3,1,5); doublechar(oct"214",7,3,2,5); doublechar(oct"220",7,4,1,5); doublechar(oct"224",7,3,1,6); doublechar(oct"230",0,5,3,7); doublechar(oct"234",7,2,1,5); doublechar(oct"240",7,3,1,4); doublechar(oct"244",6,3,1,5); doublechar(oct"250",0,3,1,6); doublechar(oct"254",0,3,2,5); doublechar(oct"260",7,4,2,5); doublechar(oct"264",7,4,1,6); doublechar(oct"270",0,5,1,7); doublechar(oct"274",7,2,1,4); doublechar(oct"300",6,3,1,4); doublechar(oct"304",0,5,3,6); doublechar(oct"310",0,3,1,7); doublechar(oct"314",5,2,1,3); doublechar(oct"320",7,4,3,5); doublechar(oct"324",7,5,1,6); doublechar(oct"330",0,5,1,7); doublechar(oct"334",7,2,1,3); doublechar(oct"340",5,3,1,4); doublechar(oct"344",7,5,3,6); doublechar(oct"350",0,5,1,6); doublechar(oct"354",0,3,2,7); doublechar(oct"360",5,2,1,4); doublechar(oct"364",7,4,3,6); def lambdachar(expr a,b,c,d) = begincchar(8a+4b+2c+d); draw p[1][5]; draw p[5][1]; if a=0: filland(p[1][5]l,p[3][7]l); else: draw p[3][7] cutafter p[1][5]; fi if b=0: filland(p[3][7]l,p[5][1]l); else: draw p[3][7] cutbefore p[5][1]; fi if c=0: filland(p[5][1]l,p[7][3]l); else: draw p[7][3] cutafter p[5][1]; fi if d=0: filland(p[7][3]l,p[1][5]l); else: draw p[7][3] cutbefore p[1][5]; fi endcchar; enddef; lambdachar(0,0,0,0); lambdachar(0,0,0,1); lambdachar(0,0,1,0); lambdachar(0,0,1,1); lambdachar(0,1,0,0); lambdachar(0,1,0,1); lambdachar(0,1,1,0); lambdachar(0,1,1,1); lambdachar(1,0,0,0); lambdachar(1,0,0,1); lambdachar(1,0,1,0); lambdachar(1,0,1,1); lambdachar(1,1,0,0); lambdachar(1,1,0,1); lambdachar(1,1,1,0); lambdachar(1,1,1,1); font_quad:=13u#; font_normal_space:=13u#; font_normal_stretch:=0; font_normal_shrink:=0; font_identifier:="CELTICA"; font_coding_scheme:="bizarre"; bye. showit; errmessage "blank"; charstopping:=true; secondarydef p then q = begingroup pair t; t=p intersectiontimes q; subpath (0,xpart t) of p & subpath(ypart t,1) of q endgroup enddef;