ramey%tilde%ti-csl.CSNET@RELAY.CS.NET (Joe Ramey) (08/28/86)
Has anyone found good values for blacker, fillin, and o_correction for the Imagen 24/300? I have been playing with it for a while, and it's becoming more difficult to tell what I am looking for in the output. One strange thing I have noticed is that the lowercase y in cmr10 at low magnifications (like magstep .5) looks funny; the bulb on the tail is hard to make appear (the tail just curls around about 180 degrees, but there is no bulb). I can make it appear with blacker set to 1.5 or so, or with o_correction set to .99 (this makes other things look real funny though). At high magnification (magstep 3) the tail looks just fine with various parameters settings. If you have good parameters for this printer, let me know. At least that way I'll have a place to start from! Joe Ramey TI Computer Science Center, Dallas
nb@COYOTE.STANFORD.EDU (Neenie Billawala) (08/30/86)
************** Dear Joe - In response to your question, the following is a copy of a note I sent to someone else who asked a similar question: How to get the CM fonts to work better on a "write-white" machine? I hope it helps. (And if it works, would you send me a sample? Thanks) -- neenie ************** The problem in getting a like result with write-white(ww)/write-black(wb) machines from the same pixel pattern lies in the fact that the effective size of each pixel differs; the size is typically smaller in ww machines. This means that you won't get the same variations in line thickness. Theoretically, one pixel on a 300dpi printer should have a width of 1/300 of an inch. On a ww machine, it's typically less; on a wb machine, it's usually a bit more. So the gradations of thickness may look something like the following: # of pixels "ideal width" ww width wb width 1 1 * 1/300inch .8 * 1/300inch 1.2*1/300inch 2 2 * 1/300inch 1.8 * 1/300inch 2.2*1/300inch 3 3 * 1/300inch 2.8 * 1/300inch 3.2*1/300inch 4 4 * 1/300inch 3.8 * 1/300inch 4.2*1/300inch 10 10 * 1/300inch 9.8 * 1/300inch 10.2*1/300inch So, you can see, the greater the number of pixels, the less important the .4 pixel difference becomes. The greatest discrepancy and problems occur with lines one pixel wide, where the % of difference is the greatest. Given these limitations, it is not possible to get exactly the same results on two such separate machines. Increasing the amount of "blacker" has the effect of adding that absolute amount to certain values; i.e., blacker:=2 would always add 2 pixels to the stem, no matter the resolution. A while back, someone came by with the same problem for a similar machine. We tried 1) some higher settings of blacker 2) selectively adding blacker to some values 3) setting a mimimum line thickness. Both 1) and 2) often created unwanted character distortions. The (tfm) widths wanted to be the same, and when e.g., each line in a character was increased by one; the shapes were often distorted, counter (inside) shapes seemed to suffer the most. A first attempt with 3) showed promise, and though the result was not as dark as the wb machine, the feeling of CM was retained. However, in the first attempt, we did not manage to change all of the thicknesses to 2 pixels. DEK made a global correction, which should keep minimum thicknesses to 2 pixels. Looking at the pixel patterns, this fix appears to work. However, the man who has the ww printer and who originally came by with this problem, is part of the University and has been traveling, so I haven't seen any concrete results yet. Such is the way of Academia! The following is an adjusted cmbase.mf file. The changes are found in 2 lines of the <font_setup> def with the comment "% "WRITE WHITE" ONLY!". Just use this file, or add the changes to yours. Then run a test, using your original mode_setup specifications. Let me know how it goes. Would you also send me a copy of your results? Thanks. Good luck. Neenie Billawala Computer Science Department Stanford University Stanford CA 94305 ************************************************************************ % The base file for Computer Modern (a supplement to {\tt plain.mf}) cmbase:=1; % when |cmbase| is known, this file has been input let cmchar=\; % `|cmchar|' should precede each character let generate=input; % `|generate|' should follow the parameters autorounding:=0; smoothing:=0; % we do our own rounding def autorounded = interim autorounding:=2 enddef; newinternal slant,fudge,math_spread,superness,superpull,beak_darkness,ligs; boolean square_dots,hefty,serifs, monospace,variant_g,low_asterisk,math_fitting; boolean dark,dark.dark,skewed,skewed.skewed; % for fast option testing dark=skewed=false; dark.dark=skewed.skewed=true; vardef Vround primary y = y_:=vround y; if y_<min_Vround: min_Vround else: y_ fi enddef; newinternal y_,min_Vround; vardef serif(suffix $,$$,@) % serif at |z$| for stroke from |z$$| (expr darkness,jut) suffix modifier = pickup crisp.nib; numeric bracket_height; pair downward; bracket_height=if dark.modifier: 1.5 fi\\ bracket; if y$<y$$: y@2=min(y$+bracket_height,y$$); top y@1-slab=bot y@0+eps=tiny.bot y$; downward=z$-z$$; if y@1>y@2: y@2:=y@1; fi else: y@2=max(y$-bracket_height,y$$); bot y@1+slab=top y@0-eps=tiny.top y$; downward=z$$-z$; if y@1<y@2: y@2:=y@1; fi fi y@3=y@2; z@3=whatever[z$,z$$]; if jut<0: z@2+penoffset downward of currentpen = z$l+penoffset downward of pen_[tiny.nib]+whatever*downward; lft x@0=lft x@1=tiny.lft x$l+jut; if x@3<x@2+eps: x@3:=x@2+eps; fi else: z@2-penoffset downward of currentpen = z$r-penoffset downward of pen_[tiny.nib]+whatever*downward; rt x@0=rt x@1=tiny.rt x$r+jut; if x@3>x@2-eps: x@3:=x@2-eps; fi fi pair corner; ypart corner=y@1; corner=z@2+whatever*downward; filldraw z@2{z$-z$$} ...darkness[corner,.5[z@1,z@2] ]{z@1-z@2} ...{jut,0}z@1--z@0--(x$,y@0)--z@3--cycle; % the serif labels (@1,@2); enddef; def dish_serif(suffix $,$$,@)(expr left_darkness,left_jut) (suffix @@)(expr right_darkness,right_jut) suffix modifier = serif($,$$,@,left_darkness,-left_jut) modifier; serif($,$$,@@,right_darkness,right_jut) modifier; if dish>0: pickup tiny.nib; numeric dish_out,dish_in; if y$<y$$: dish_out=bot y$; dish_in=dish_out+dish; let rev_=reverse; else: dish_out=top y$; dish_in=dish_out-dish; let rev_=relax; fi erase fill rev_ ((x@1,dish_out)..(x$,dish_in){right}..(x@@1,dish_out)--cycle); fi enddef; def nodish_serif(suffix $,$$,@)(expr left_darkness,left_jut) (suffix @@)(expr right_darkness,right_jut) suffix modifier = serif($,$$,@,left_darkness,-left_jut) modifier; serif($,$$,@@,right_darkness,right_jut) modifier; enddef; vardef sloped_serif.l(suffix $,$$,@)(expr darkness,jut,drop) = pickup crisp.nib; pos@2(slab,90); lft x@0=tiny.lft x$l; rt x@1=tiny.rt x$r; top y@1=tiny.top y$r; lft x@2=lft x@0-jut; y@2r=y@1-drop; y@0=max(y@2l-bracket,y$$)-eps; if drop>0: erase fill z@1--top z@1 --(x@2r,top y@1)--z@2r--cycle; fi % erase excess at top filldraw z@1--z@2r--z@2l{right} ...darkness[(x@0,y@2l),.5[z@2l,z@0] ]{z@0-z@2l} ...{down}z@0--(x@1,y@0)--cycle; % sloped serif labels(@0,@1,@2); enddef; vardef sloped_serif.r(suffix $,$$,@)(expr darkness,jut,drop) = pickup crisp.nib; pos@2(slab,-90); rt x@0=tiny.rt x$r; lft x@1=tiny.lft x$l; bot y@1=tiny.bot y$l; rt x@2=rt x@0+jut; y@2r=y@1+drop; y@0=min(y@2l+bracket,y$$)+eps; if drop>0: erase fill z@1--bot z@1 --(x@2r,bot y@1)--z@2r--cycle; fi % erase excess at bottom filldraw z@1--z@2r--z@2l{left} ...darkness[(x@0,y@2l),.5[z@2l,z@0] ]{z@0-z@2l} ...{up}z@0--(x@1,y@0)--cycle; % sloped serif labels(@0,@1,@2); enddef; vardef term.l(suffix $,$$)(expr d,t,s)= % ``robust'' sans-serif terminal path p_; p_=z$l{d}..tension t..z$$l; pair d_; d_=(x$$l-x$l,s*(y$$l-y$l)); if (abs angle direction 1 of p_ < abs angle d_)<>(x$l<x$$l): p_:=z$l{d}..tension atleast t..{d_}z$$l; fi p_ enddef; vardef term.r(suffix $,$$)(expr d,t,s)= path p_; p_=z$r{d}..tension t..z$$r; pair d_; d_=(x$$r-x$r,s*(y$$r-y$r)); if (abs angle direction 1 of p_ < abs angle d_)<>(x$r<x$$r): p_:=z$r{d}..tension atleast t..{d_}z$$r; fi p_ enddef; def rterm=reverse term enddef; vardef arm(suffix $,$$,@)(expr darkness,jut) = % arm from |z$| to |z$$| x@0=good.x(x$$r-jut); y@0=y$r; if serifs: y@1=y$l; z@1=z$$l+whatever*(z$$r-z@0); z@2=.5[z$l,z@1]; filldraw z$$l{z@1-z$$l}...darkness[z@1,.5[z@2,z$$l] ]...z@2 ---z$l--z$r--z@0--z$$r--cycle; % arm and beak else: filldraw z$l--z$r--z@0--z$$r--cycle; fi % sans-serif arm penlabels(@0,@1,@2); enddef; def pi_stroke = pickup fine.nib; pos1(hair,0); pos2(vstem,-90); pos3(vstem,-90); x1-.5hair=hround -.5hair; x2=2u; x3=w-1.5u; y1=x_height-x_height/3.141592653589793; y2=y3; top y3l=x_height; filldraw circ_stroke z3e---z2e...{x1-x2,3.14159(y1-y2)}z1e enddef; def bulb(suffix $,$$,$$$) = z$$$r=z$$r; path_.l:=z$l{x$$r-x$r,0}...{0,y$$r-y$r}z$$l; filldraw path_.l--z$$r{0,y$r-y$$r}...{x$r-x$$r,0}z$r--cycle; % link path_.r:=z$$$l{0,y$r-y$$r}..z$$$r{0,y$$r-y$r}; % near-circle filldraw subpath(0,xpart(path_.r intersectiontimes path_.l)) of path_.r --z$$r{0,y$$r-y$r}..cycle; % bulb enddef; def v_bulb(suffix $,$$)= % |pos$| is known y$$+.5curve=x_height+oo; x$$+.5curve=w-u; numeric theta; theta=angle(4(x$-x$$),y$-y$$); pos$$(curve,theta+90); filldraw z$$l{dir theta}..tension atleast 1 and 1..{down}z$l --z$r{up}...{-dir theta}z$$r..cycle; % bulb enddef; def dot(suffix $,$$) = filldraw if square_dots: (x$l,y$$l)--(x$r,y$$l) --(x$r,y$$r)--(x$l,y$$r)--cycle % squarish dot else: z$l...z$$l...z$r...z$$r...cycle fi % roundish dot enddef; def comma(suffix $,@)(expr dot_size,jut,depth) = pickup fine.nib; pos$(dot_size,90); if square_dots: pos$'(dot_size,0); z$'=z$; dot($',$); % squarish dot comma_join_:=max(fine.breadth,floor .7dot_size); comma_bot_:=max(fine.breadth,floor .5dot_size); pos@0(comma_join_,0); pos@1(comma_join_,0); pos@2(comma_bot_,0); y@0=y$; y@1=y$l; y@2=y@1-depth; x@0r=x@1r=x$'r; rt x@2r=good.x(x$-eps); filldraw stroke z@0e--z@1e..z@2e; % tail else: pos@1(vair,90); pos@2(vair,0); pos@3(vair,-45); z@1r=z$r; rt x@2r=hround(x$+.5dot_size+jut)+2eps; x@3=x$-.5u; y@2=1/3[y@1,y@3]; bot y@3r=vround(y$-.5dot_size-depth); y_:=ypart((z@1{right}...z@2{down}...z@3) intersectiontimes (z$l{right}..{left}z$r)); if y_<0: y_:=1; fi filldraw z$r{left}..subpath (0,y_) of (z$l{right}..{left}z$r)--cycle; % dot filldraw stroke z@1e{right}...z@2e{down}...z@3e; fi % tail penlabels(@1,@2,@3); enddef; def ammoc(suffix $,@)(expr dot_size,jut,depth) = % reversed comma pickup fine.nib; pos$(dot_size,90); if square_dots: pos$'(dot_size,0); z$'=z$; dot($',$); % squarish dot comma_join_:=max(fine.breadth,floor .7dot_size); comma_top_:=max(fine.breadth,floor .5dot_size); pos@0(comma_join_,0); pos@1(comma_join_,0); pos@2(comma_top_,0); y@0=y$; y@1=y$r; y@2=y@1+depth; x@0l=x@1l=x$'l; lft x@2l=good.x(x$+eps); filldraw stroke z@0e--z@1e..z@2e; % tail else: pos@1(vair,90); pos@2(vair,0); pos@3(vair,-45); z@1l=z$l; lft x@2l=hround(x$-.5dot_size-jut)-2eps; x@3=x$+.5u; y@2=1/3[y@1,y@3]; top y@3l=vround(y$+.5dot_size+depth); y_:=ypart((z@1{left}...z@2{up}...z@3) intersectiontimes (z$r{left}..{right}z$l)); if y_<0: y_:=1; fi filldraw z$l{right}..subpath (0,y_) of (z$r{left}..{right}z$l)--cycle; % dot filldraw stroke z@1e{left}...z@2e{up}...z@3e; fi % tail penlabels(@1,@2,@3); enddef; %%% @ from to %%%% temporary formatting change vardef diag_in(suffix from,$)(expr sharpness)(suffix $$) = pickup tiny.nib; save from_x,y_; if y.from>y$: bot else: top fi\\ y_=y$; (from_x,y_)=whatever[z.from,z$]; sharpness[z$,(from_x,y_)]{z$-z.from} ...{z$$-z$}z$+sharpness*length(z$-(from_x,y_))*unitvector(z$$-z$) enddef; vardef diag_out(suffix $)(expr sharpness)(suffix $$,to) = pickup tiny.nib; save to_x,y_; if y.to>y$: bot else: top fi\\ y_=y$; (to_x,y_)=whatever[z$$,z.to]; z$$-sharpness*length(z$$-(to_x,y_))*unitvector(z$$-z$){z$$-z$} ...{z.to-z$$}sharpness[z$$,(to_x,y_)] enddef; vardef diag_end(suffix from,$)(expr sharpness_in,sharpness_out)(suffix $$,to)= save from_x,to_x,y_,x_,xx_; if y.from>y$: tiny.bot else: tiny.top fi\\ y_=y$; % we assume that |y$=y$$| (from_x,y_)=whatever[z.from,z$]; (to_x,y_)=whatever[z$$,z.to]; if x$$>x$: x_=x$+sharpness_in*length(z$-(from_x,y_)); xx_=x$$-sharpness_out*length(z$$-(to_x,y_)); if xx_<x_: xx_:=x_:=.5[xx_,x_]; fi else: x_=x$-sharpness_in*length(z$-(from_x,y_)); xx_=x$$+sharpness_out*length(z$$-(to_x,y_)); if xx_>x_: xx_:=x_:=.5[xx_,x_]; fi fi sharpness_in[z$,(from_x,y_)]{z$-z.from} ...{z$$-z$}(x_,y$)..(xx_,y$){z$$-z$} ...{z.to-z$$}sharpness_out[z$$,(to_x,y_)] enddef; %%% at from to %%%% restore normal formatting vardef special_diag_end(suffix $$,$,@,@@) = % for top middle of w's if x@r<=x$r: diag_end($$r,$r,1,1,@l,@@l) else: z0=whatever[z$$l,z$l]=whatever[z@l,z@@l]; diag_end($$r,$r,1,1,$l,0)--z0 fi enddef; def prime_points_inside(suffix $,$$) = theta_:=angle(z$r-z$l); penpos$'(whatever,theta_); if y$$>y$: z$'=(0,pen_top) rotated theta_ + whatever[z$l,z$r]; theta_:=angle(z$$-z$)-90; else: z$'=(0,pen_bot) rotated theta_ + whatever[z$l,z$r]; theta_:=angle(z$$-z$)+90; fi z$'l+(pen_lft,0) rotated theta_=z$l+whatever*(z$-z$$); z$'r+(pen_rt,0) rotated theta_=z$r+whatever*(z$-z$$); enddef; def ellipse_set(suffix $,@,@@,$$) = % given |z$,x@,z$$|, find |y@| and |z@@| % such that the path |z${x@-x$,0}..z@{0,y@-y$}..{z$$-z@@}z@@| % is consistent with an ellipse % and such that the line |z@@--z$$| has a given |slope| alpha_:=slope*(x@-x$); beta_:=y$$-y$-slope*(x$$-x$); gamma_:=alpha_/beta_; y@-y$=.5(beta_-alpha_*gamma_); x@@-x$=-2gamma_*(x@-x$)/(1+gamma_*gamma_); y@@-y$$=slope*(x@@-x$$) enddef; vardef diag_ratio(expr a,b,y,c) = % assuming that $a>\vert b/y\vert$, % compute the value $\alpha=(x\6{++}y)/y$ such that $ax+b\alpha=c$ numeric a_,b_; b_=b/y; a_=a*a-b_*b_; (a*(c++y*sqrt a_)-b_*c)/a_/y enddef; def f_stroke(suffix $,$$,@,left_serif,right_serif)(expr left_jut,right_jut)= pickup tiny.nib; bot y$=0; penpos@0(x$r-x$l,0); x@0l=x$l; top y@0=x_height; filldraw stroke z$e--z@0e; % stem pickup fine.nib; pos@0'(x$r-x$l-(hround stem_corr)+tiny,180); y@0'=y@0; lft x@0'r=tiny.lft x$l; penpos@1(x@0'l-x@0'r,180); x@1=x@0'; y@1+.5vair=.5[x_height,h]; pos@2(vair,90); top y@2r=h+oo; if serifs: x@2=.6[x@1,x$$r]; (x@,y@2r)=whatever[z@2l,z@1l]; x@2r:=min(x@,.5[x@2,x$$r]); pos@3(hair,0); bulb(@2,@3,$$); % bulb filldraw stroke z@0'e--z@1e & super_arc.e(@1,@2); % arc dish_serif($,@0,left_serif,1/3,left_jut,right_serif,1/3,right_jut); % serif else: x@2=.6[x@1,x$$]; y@1l:=1/3[y@1l,y@2l]; filldraw stroke z@0'e--z@1e & super_arc.e(@1,@2) & term.e(@2,$$,right,.9,4); fi % arc and terminal penlabels(@0,@1,@2); enddef; def h_stroke(suffix $,@,@@,$$) = penpos$$(x@@r-x@@l,0); x$$=x@@; bot y$$=0; y@@=1/3[bar_height,x_height]; penpos$''(x$r-x$l,0); x$''=x$; y$''=1/8[bar_height,x_height]; filldraw stroke z$''e--z$e; % thicken the lower left stem penpos@0(min(rt x$r-lft x$l,thin_join)-fine,180); pickup fine.nib; rt x@0l=tiny.rt x$r; y@0=y$''; pos@1(vair,90); pos@@'(x@@r-x@@l+tiny,0); z@@'=z@@; x@1=.5[rt x@0l,rt x@@'r]; top y@1r=x_height+oo; (x@,y@1l)=whatever[z@1r,z@0l]; x@1l:=x@; filldraw stroke z@0e{up}...{right}z@1e &{{interim superness:=hein_super; super_arc.e(@1,@@')}}; % arch pickup tiny.nib; filldraw stroke z@@e--z$$e; % right stem labels(@0); penlabels(@1); enddef; def hook_out(suffix $,$$,$$$)suffix modifier= % |x$| and |x$$$| (only) are known pos$(stem,0); pos$$(vair,90); x$$$:=hround(x$$$+.5hair-eps)-.5hair; pos$$$(hair,180); y$=1/4x_height; bot y$$l=-oo; y$$$=1/3x_height; if skewed.modifier: x$$=x$+1.25u; filldraw stroke z$e{-u,-x_height}...z$$e{right}...{up}z$$$e; % hook else: x$$=x$+1.5u; filldraw stroke z$e{down}...z$$e{right} ...{x$$$-(x$+2.5u),x_height}z$$$e; fi enddef; % hook def hook_in(suffix $,$$,$$$)suffix modifier= % |x$| and |x$$$| (only) are known x$:=hround(x$-.5hair)+.5hair; pos$(hair,180); pos$$(vair,90); pos$$$(stem,0); y$=2/3x_height; top y$$r=x_height+oo; y$$$=3/4x_height; if skewed.modifier: x$$=x$$$-1.25u; filldraw stroke z$e{up}...z$$e{right}...{-u,-x_height}z$$$e; % hook else: x$$=x$$$-1.5u; filldraw stroke z$e{x$$$-2.5u-x$,x_height} ...z$$e{right}...{down}z$$$e; fi enddef; % hook def ital_arch(suffix $,$$,$$$) = % |z$| and |z$$$| (only) are known pos$'(hair,180); z$'=z$; pos$$(vair,90); pos$$$(stem,0); {{interim superness := more_super; x$$=.6[x$,x$$$]; top y$$r=x_height+oo; y$$$=.65x_height; filldraw stroke z$'e{up}...super_arc.e($$,$$$);}} enddef; % stroke def compute_spread(expr normal_spread,big_spread)= spread#:=math_spread[normal_spread,big_spread]; spread:=ceiling(spread#*hppp)+eps; enddef; def v_center(expr h_sharp) = .5h_sharp+math_axis#, .5h_sharp-math_axis# enddef; def circle_points = x4=x8=.5[x2,x6]; x1=x3=superness[x4,x2]; x5=x7=superness[x4,x6]; y2=y6=.5[y4,y8]; y1=y7=superness[y2,y8]; y3=y5=superness[y2,y4]; enddef; def draw_circle = draw z8{right}...z1{z2-z8}...z2{down}...z3{z4-z2}...z4{left} ...z5{z6-z4}...z6{up}...z7{z8-z6}...cycle enddef; def left_paren(expr min_breadth, max_breadth) = pickup fine.nib; pos1(hround min_breadth,0); pos2(hround max_breadth,0); pos3(hround min_breadth,0); rt x1r=rt x3r=hround(w-1.25u+.5min_breadth); lft x2l=hround 1.25u; top y1=h; y2=.5[y1,y3]; bot y3=1-d; filldraw stroke z1e{3(x2e-x1e),y2-y1}...z2e ...{3(x3e-x2e),y3-y2}z3e; % arc penlabels(1,2,3); enddef; def right_paren(expr min_breadth, max_breadth) = pickup fine.nib; pos1(hround min_breadth,0); pos2(hround max_breadth,0); pos3(hround min_breadth,0); lft x1l=lft x3l=hround(1.25u-.5min_breadth); rt x2r=hround(w-1.25u); top y1=h; y2=.5[y1,y3]; bot y3=1-d; filldraw stroke z1e{3(x2e-x1e),y2-y1}...z2e ...{3(x3e-x2e),y3-y2}z3e; % arc penlabels(1,2,3); enddef; def left_bracket(expr breadth,do_top,do_bot) = pickup crisp.nib; numeric thickness; thickness=hround breadth; pos1(thickness,0); pos2(thickness,0); top y1=h; bot y2=1-d; lft x1l=lft x2l=hround(2.5u-.5thickness); filldraw stroke z1e--z2e; % stem pos3(thickness,90); pos4(thickness,90); pos5(thickness,90); pos6(thickness,90); x3=x5=x1l; rt x4=rt x6=hround(w-.75u+.5thickness); y3r=y4r=y1; y5l=y6l=y2; if do_top: filldraw stroke z3e--z4e; fi % upper bar if do_bot: filldraw stroke z5e--z6e; fi % lower bar penlabels(1,2,3,4,5,6); enddef; def right_bracket(expr breadth,do_top,do_bot) = pickup crisp.nib; numeric thickness; thickness=hround breadth; pos1(thickness,0); pos2(thickness,0); top y1=h; bot y2=1-d; rt x1r=rt x2r=hround(w-2.5u+.5thickness); filldraw stroke z1e--z2e; % stem pos3(thickness,90); pos4(thickness,90); pos5(thickness,90); pos6(thickness,90); x3=x5=x1r; lft x4=lft x6=hround(.75u-.5thickness); y3r=y4r=y1; y5l=y6l=y2; if do_top: filldraw stroke z3e--z4e; fi % upper bar if do_bot: filldraw stroke z5e--z6e; fi % lower bar penlabels(1,2,3,4,5,6); enddef; def left_curly(expr min_breadth, max_breadth) = pickup fine.nib; forsuffixes $=1,1',4,4',7,7': pos$(hround min_breadth,0); endfor forsuffixes $=2,3,5,6: pos$(hround max_breadth,0); endfor x2=x3=x5=x6; x1=x1'=x7=x7'=w-x4=w-x4'; lft x4l=hround(1.5u-.5min_breadth); lft x2l=hround(.5w-.5max_breadth); top y1=h; bot y7=1-d; .5[y4,y4']=.5[y1,y7]=.5[y2,y6]=.5[y3,y5]; y1-y2=y3-y4=(y1-y4)/4; y1-y1'=y4-y4'=y7'-y7=vround(min_breadth-fine); filldraw z1l{3(x2l-x1l),y2-y1}...z2l---z3l...{3(x4l-x3l),y4-y3}z4l --z4'l{3(x5l-x4l),y5-y4'}...z5l---z6l...{3(x7l-x6l),y7-y6}z7l --z7r--z7'r{3(x6r-x7r),y6-y7'}...z6r---z5r ...{3(x4r-x5r),.5[y4,y4']-y5}.5[z4r,z4'r]{3(x3r-x4r),y3-.5[y4,y4']} ...z3r---z2r...{3(x1r-x2r),y1'-y2}z1'r--z1r--cycle; % stroke penlabels(1,2,3,4,5,6,7); enddef; def right_curly(expr min_breadth, max_breadth) = pickup fine.nib; forsuffixes $=1,1',4,4',7,7': pos$(hround min_breadth,0); endfor forsuffixes $=2,3,5,6: pos$(hround max_breadth,0); endfor x2=x3=x5=x6; x1=x1'=x7=x7'=w-x4=w-x4'; lft x1l=hround(1.5u-.5min_breadth); lft x2l=hround(.5w-.5max_breadth); top y1=h; bot y7=1-d; .5[y4,y4']=.5[y1,y7]=.5[y2,y6]=.5[y3,y5]; y1-y2=y3-y4=(y1-y4)/4; y1-y1'=y4-y4'=y7'-y7=vround(min_breadth-fine); filldraw z1r{3(x2r-x1r),y2-y1}...z2r---z3r...{3(x4r-x3r),y4-y3}z4r --z4'r{3(x5r-x4r),y5-y4'}...z5r---z6r...{3(x7r-x6r),y7-y6}z7r --z7l--z7'l{3(x6l-x7l),y6-y7'}...z6l---z5l ...{3(x4l-x5l),.5[y4,y4']-y5}.5[z4l,z4'l]{3(x3l-x4l),y3-.5[y4,y4']} ...z3l---z2l...{3(x1l-x2l),y1'-y2}z1'l--z1l--cycle; % stroke penlabels(1,2,3,4,5,6,7); enddef; def left_angle(expr breadth) = pickup pencircle scaled breadth; x1=x3=good.x(w-u)+eps; lft x2=hround u-eps; top y1=h+eps; .5[y1,y3]=y2=good.y .5[-d+eps,h]; draw z1--z2--z3; % diagonals labels(1,2,3); enddef; def right_angle(expr breadth) = pickup pencircle scaled breadth; x1=x3=good.x u-eps; rt x2=hround(w-u)+eps; top y1=h+eps; .5[y1,y3]=y2=good.y .5[-d+eps,h]; draw z1--z2--z3; % diagonals labels(1,2,3); enddef; def big_slash(expr breadth) = adjust_fit(-letter_fit#,-letter_fit#); pickup pencircle scaled breadth; rt x1=hround(w-u); lft x2=hround u; top y1=h+eps; bot y2=1-d-eps; draw z1--z2; % diagonal labels(1,2); enddef; def big_blash(expr breadth) = adjust_fit(-letter_fit#,-letter_fit#); pickup pencircle scaled breadth; lft x1=hround u; rt x2=hround(w-u); top y1=h+eps; bot y2=1-d-eps; draw z1--z2; % diagonal labels(1,2); enddef; def big_sqrt = adjust_fit(0,-letter_fit#); pickup rule.nib; x1=good.x 4/9w; x2=good.x(w+.5); bot y1=-d; bot y2=0; draw z1--z2; % diagonal pickup crisp.nib; pos3(max(curve,rule_thickness),0); x3l=1.5[x2,x1]; y3=.5[y1,y2]; pos4(rule_thickness,0); x4=x1; bot y4=-d; pos5(vair,-45); x5l=good.x(x3l-u); z5l=whatever[z3r,z2]; z6=z5r+whatever*(z2-z3r)=whatever[z3l,z4l]; z7=whatever[z1,z2]=z3r+whatever*(z4l-z3l); filldraw z5r--z6--z4l--z4--z7--z3r--z5l--cycle; % left diagonal and serif penlabels(1,2,3,4,5,6,7); enddef; def big_hat = adjust_fit(0,0); pickup crisp.nib; pos2(.6[vair,curve],90); top y2r=h+o; x2=.5w; x1=w-x3=good.x -eps; y1=y3=.5[x_height,y2]; pos1(hair,angle(z2-z1)+90); pos3(hair,angle(z3-z2)+90); filldraw stroke z1e--z2e--z3e; % diagonals penlabels(1,2,3); enddef; def big_tilde = adjust_fit(0,0); pickup crisp.nib; numeric theta; theta=angle(1/6(w-vair),1/4(h-x_height)); numeric mid_width; mid_width=.4[vair,stem]; pos1(vair,theta+90); pos2(vair,theta+90); pos3(vair,theta+90); pos4(vair,theta+90); z2-z1=z4-z3=(mid_width-crisp)*dir theta; lft x1r=w-rt x4l=0; top y4r=h; bot y1l=vround(bot y1l+min(2/3[x_height,h],y3l-.25vair)-top y1r); pair delta; ypart delta=3(y3l-y1l); delta=whatever*dir theta; filldraw z1l..controls(z1l+delta)and(z3l-delta)..z3l..z4l --z4r..controls(z4r-delta)and(z2r+delta)..z2r..z1r--cycle; % stroke penlabels(1,2,3,4); enddef; def beginarithchar(expr c) = % ensure consistent dimensions for $+$, $-$, etc. if monospace: beginchar(c,14u#,27/7u#+math_axis#,27/7u#-math_axis#); else: beginchar(c,14u#,6u#+math_axis#,6u#-math_axis#); fi italcorr math_axis#*slant-.5u#; adjust_fit(0,0); enddef; newinternal l,r,shrink_fit; % adjustments to spacing def normal_adjust_fit(expr left_adjustment,right_adjustment) = l:=-hround(left_adjustment*hppp)-letter_fit; interim xoffset:=-l; charwd:=charwd+2letter_fit#+left_adjustment+right_adjustment; r:=l+hround(charwd*hppp)-shrink_fit; w:=r-hround(right_adjustment*hppp)-letter_fit; enddef; def mono_adjust_fit(expr left_adjustment,right_adjustment) = numeric expansion_factor; mono_charwd#=2letter_fit# +expansion_factor*(charwd+left_adjustment+right_adjustment); forsuffixes $=u,jut,cap_jut,beak_jut,apex_corr: $:=$.#*expansion_factor*hppp; endfor l:=-hround(left_adjustment*expansion_factor*hppp)-letter_fit; interim xoffset:=-l; r:=l+mono_charwd-shrink_fit; w:=r-hround(right_adjustment*expansion_factor*hppp)-letter_fit; charwd:=mono_charwd#; charic:=mono_charic#; enddef; extra_endchar:=extra_endchar&"r:=r+shrink_fit;w:=r-l;"; def ignore_math_fit(expr left_adjustment,right_adjustment) = enddef; def do_math_fit(expr left_adjustment,right_adjustment) = l:=l-hround(left_adjustment*hppp); interim xoffset:=-l; charwd:=charwd+left_adjustment+right_adjustment; r:=l+hround(charwd*hppp)-shrink_fit; charic:=charic-right_adjustment; if charic<0: charic:=0; fi enddef; def zero_width = charwd:=0; r:=l-shrink_fit enddef; def change_width = if not monospace: % change width by $\pm1$ if r+shrink_fit-l=floor(charwd*hppp): w:=w+1; r:=r+1; else: w:=w-1; r:=r-1; fi fi enddef; def padded expr del_sharp = charht:=charht+del_sharp; chardp:=chardp+del_sharp enddef; def font_setup = if monospace: let adjust_fit=mono_adjust_fit; def mfudged=fudged enddef; mono_charic#:=body_height#*slant; if mono_charic#<0: mono_charic#:=0; fi mono_charwd#:=9u#; define_whole_pixels(mono_charwd); else: let adjust_fit=normal_adjust_fit; def mfudged= enddef; fi if math_fitting: let math_fit=do_math_fit else: let math_fit=ignore_math_fit fi; define_pixels(u,width_adj,serif_fit,cap_serif_fit,jut,cap_jut,beak, bar_height,dish,bracket,beak_jut,stem_corr,vair_corr,apex_corr); define_blacker_pixels(notch_cut,cap_notch_cut); define_whole_pixels(letter_fit,fine,crisp,tiny); define_whole_vertical_pixels(body_height,asc_height, cap_height,fig_height,x_height,comma_depth,desc_depth,serif_drop); define_whole_blacker_pixels(thin_join,hair,stem,curve,flare, dot_size,cap_hair,cap_stem,cap_curve); define_whole_vertical_blacker_pixels(vair,bar,slab,cap_bar,cap_band); define_corrected_pixels(o,apex_o); forsuffixes $=hair,stem,cap_stem: fudged$.#:=fudge*$.#; fudged$:=hround(fudged$.#*hppp+blacker); forever: exitif fudged$>.9fudge*$; fudged$:=fudged$+1; endfor endfor rule_thickness:=ceiling(rule_thickness#*hppp); heavy_rule_thickness:=ceiling(3rule_thickness#*hppp); oo:=vround(.5o#*hppp*o_correction)+eps; apex_oo:=vround(.5apex_o#*hppp*o_correction)+eps; lowres_fix(stem,curve,flare) 1.3; lowres_fix(stem,curve) 1.2; lowres_fix(cap_stem,cap_curve) 1.2; lowres_fix(hair,cap_hair) 1.2; lowres_fix(cap_band,cap_bar,bar,slab) 1.2; stem':=hround(stem-stem_corr); cap_stem':=hround(cap_stem-stem_corr); vair':=vround(vair+vair_corr); vstem:=vround .8[vair,stem]; cap_vstem:=vround .8[vair,cap_stem]; ess:=(ess#/stem#)*stem; cap_ess:=(cap_ess#/cap_stem#)*cap_stem; dw:=(curve#-stem#)*hppp; bold:=curve#*hppp+blacker; dh#:=.6designsize; stem_shift#:=if serifs: 2stem_corr# else: 0 fi; more_super:=max(superness,sqrt .77superness); hein_super:=max(superness,sqrt .81225258superness); % that's $2^{-.3}$ clear_pen_memory; if fine=0: fine:=1; fi forsuffixes $=fine,crisp,tiny: %%% fine $ %%%% temporary formatting convention for MFT if $>fudged.hair: $:=fudged.hair; fi $.breadth:=$; pickup if $=0: nullpen else: pencircle scaled $; $:=$-eps fi; $.nib:=savepen; breadth_[$.nib]:=$; forsuffixes $$=lft,rt,top,bot: shiftdef($.$$,$$ 0); endfor endfor %%% @ $ %%%% restore ordinary formatting for $ min_Vround:=max(fine.breadth,crisp.breadth,tiny.breadth,2); % "WRITE WHITE" ONLY! if min_Vround<vround min_Vround: min_Vround:=vround min_Vround; fi if flare<vround flare: flare:=vround flare; fi forsuffixes $=vair,bar,slab,cap_bar,cap_band,vair',vstem,cap_vstem,bold: if $<min_Vround: $:=min_Vround; fi endfor pickup pencircle scaled rule_thickness; rule.nib:=savepen; math_axis:=good.y(math_axis#*hppp); pickup pencircle scaled if hefty:(.6[vair,fudged.hair]) else:fudged.hair fi; light_rule.nib:=savepen; pickup pencircle xscaled cap_curve yscaled cap_hair rotated 30; cal.nib:=savepen; pair cal.extension; cal.extension:=(.75cap_curve,0) rotated 30; pickup pencircle xscaled cap_curve yscaled cap_hair rotated 70; tilted.nib:=savepen; pickup pencircle xscaled curve yscaled cap_hair rotated 70; med_tilted.nib:=savepen; pickup pencircle xscaled cap_stem yscaled cap_hair rotated 30; med_cal.nib:=savepen; pickup pencircle xscaled stem yscaled cap_hair rotated 30; light_cal.nib:=savepen; pickup pencircle xscaled(cap_curve+dw) yscaled cap_hair rotated 30; heavy_cal.nib:=savepen; bot_flourish_line:=-.5u-o; pair bend; bend=(.5u,0); pair flourish_change; flourish_change=(4u,.2asc_height); join_radius:=u; currenttransform:=identity slanted slant yscaled aspect_ratio scaled granularity; if currenttransform=identity: let t_=relax else: def t_ = transformed currenttransform enddef fi; numeric paren_depth#; .5[body_height#,-paren_depth#]=math_axis#; numeric asc_depth#; .5[asc_height#,-asc_depth#]=math_axis#; body_depth:=desc_depth+body_height-asc_height; shrink_fit:=1+hround(2letter_fit#*hppp)-2letter_fit; if not string mode: if mode<=smoke: shrink_fit:=0; fi fi forsuffixes $=thin_join,hair,curve,flare,dot_size,cap_hair,cap_curve, vair,bar,slab,cap_bar,cap_band,stem',cap_stem',vair',fudged.hair, fudged.stem,fudged.cap_stem: $:=max($,2); endfor % "WRITE WHITE" ONLY! enddef; def shiftdef(suffix $)(expr delta) = vardef $ primary x = x+delta enddef enddef; def makebox(text rule) = for y=0,asc_height,body_height,x_height,bar_height,-desc_depth,-body_depth: rule((l,y)t_,(r,y)t_); endfor % horizontals for x=l,r: rule((x,-body_depth)t_,(x,body_height)t_); endfor % verticals for x=u*(1+floor(l/u)) step u until r-1: rule((x,-body_depth)t_,(x,body_height)t_); endfor % more verticals if charic<>0: rule((r+charic*pt,h.o_),(r+charic*pt,.5h.o_)); fi % italic correction enddef; def maketicks(text rule) = for y=0,h.o_,-d.o_: rule((l,y),(l+10,y)); rule((r-10,y),(r,y)); endfor % horizontals for x=l,r: rule((x,10-d.o_),(x,-d.o_)); rule((x,h.o_-10),(x,h.o_)); endfor % verticals if charic<>0: rule((r+charic*pt,h.o_-10),(r+charic*pt,h.o_)); fi % italic correction enddef; rulepen:=pensquare; vardef stroke text t = forsuffixes e = l,r: path_.e:=t; endfor if cycle path_.l: errmessage "Beware: `stroke' isn't intended for cycles"; fi path_.l -- reverse path_.r -- cycle enddef; vardef circ_stroke text t = forsuffixes e = l,r: path_.e:=t; endfor if cycle path_.l: errmessage "Beware: `stroke' isn't intended for cycles"; fi path_.l -- reverse path_.r .. cycle enddef; vardef super_arc.r(suffix $,$$) = % outside of super-ellipse pair center,corner; if y$=y$r: center=(x$$r,y$r); corner=(x$r,y$$r); else: center=(x$r,y$$r); corner=(x$$r,y$r); fi z$.r{corner-z$.r}...superness[center,corner]{z$$.r-z$.r} ...{z$$.r-corner}z$$.r enddef; vardef super_arc.l(suffix $,$$) = % inside of super-ellipse pair center,corner; if y$=y$r: center=(x$$l,y$l); corner=(x$l,y$$l); else: center=(x$l,y$$l); corner=(x$$l,y$l); fi z$l{corner-z$l}...superness[center,corner]{z$$l-z$l} ...{z$$l-corner}z$$l enddef; vardef pulled_super_arc.r(suffix $,$$)(expr superpull) = pair center,corner; if y$=y$r: center=(x$$r,y$r); corner=(x$r,y$$r); else: center=(x$r,y$$r); corner=(x$$r,y$r); fi z$r{corner-z$r}...superness[center,corner]{z$$r-z$r} ...{z$$r-corner}z$$r enddef; vardef pulled_super_arc.l(suffix $,$$)(expr superpull) = pair center,corner,outer_point; if y$=y$r: center=(x$$l,y$l); corner=(x$l,y$$l); outer_point=superness[(x$$r,y$r),(x$r,y$$r)]; else: center=(x$l,y$$l); corner=(x$$l,y$l); outer_point=superness[(x$r,y$$r),(x$$r,y$r)]; fi z$l{corner-z$l} ...superpull[superness[center,corner],outer_point]{z$$l-z$l} ...{z$$l-corner}z$$l enddef; vardef pulled_arc@#(suffix $,$$) = pulled_super_arc@#($,$$)(superpull) enddef; vardef serif_arc(suffix $,$$) = z${x$$-x$,0}...(.75[x$,x$$],.25[y$,y$$]){z$$-z$}...{0,y$$-y$}z$$ enddef; vardef penpos@#(expr b,d) = if known b: if b<=0: errmessage "bad penpos"; fi fi (x@#r-x@#l,y@#r-y@#l)=(b,0) rotated d; x@#=.5(x@#l+x@#r); y@#=.5(y@#l+y@#r) enddef; newinternal currentbreadth; vardef pos@#(expr b,d) = if known b: if b<=currentbreadth: errmessage "bad pos"; fi fi (x@#r-x@#l,y@#r-y@#l)=(b-currentbreadth,0) rotated d; x@#=.5(x@#l+x@#r); y@#=.5(y@#l+y@#r) enddef; def numeric_pickup_ primary q = currentpen:=pen_[q]; pen_lft:=pen_lft_[q]; pen_rt:=pen_rt_[q]; pen_top:=pen_top_[q]; pen_bot:=pen_bot_[q]; currentpen_path:=pen_path_[q]; if known breadth_[q]: currentbreadth:=breadth_[q]; fi enddef; vardef ic# = charic enddef; vardef h# = charht enddef; vardef w# = charwd enddef; vardef d# = chardp enddef; let {{=begingroup; let }}=endgroup; def .... = .. tension atleast .9 .. enddef; def less_tense = save ...; let ...=.... enddef; def ?? = hide(showvariable x,y) enddef; let semi_ =;; let colon_ = :; let endchar_ = endchar; def iff expr b = if b:let next_=use_it else:let next_=lose_it fi; next_ enddef; def use_it = let : = restore_colon; enddef; def restore_colon = let : = colon_; enddef; def lose_it = let endchar=fi; inner cmchar; let ;=fix_ semi_ if false enddef; def fix_=let ;=semi_; let endchar=endchar_; outer cmchar; enddef; def always_iff = let : = endgroup; killboolean enddef; def killboolean text t = use_it enddef; outer cmchar;