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;