% \iffalse
%<dtx>\ProvidesFile{vnbase.dtx}[2003/11/01 v01.01 VNR.KTV.DTX.Base]
% \fi
%
% \section{Basic macros}
%
% \begin{macrocode}
%<*vnbase>
% \end{macrocode}
%
% ��nh ngh�a t�t c� c�c macro ���c d�ng b�i |VNR|.
%
% \subsection{Generic Macros}
%
% \danger
% V� |mfplain.mp| kh�ng ���c c�p nh�t c�ng v�i |plain.mf|,
% n�n �� |MetaPost| c� th� l�m vi�c v�i |ec| fonts,
% ta ph�i c�n c�c d�ng sau (ch�p t� |plain.mf|).
% \endanger
%
% \begin{macrocode}
%<*test>
vardef whatever = save ?; ? enddef;
def killtext text t = enddef;
%</test>
% \end{macrocode}
%
% \begin{macrocode}
if unknown exbase:
input exbase;
fi;
% \end{macrocode}
%
% \begin{macrocode}
if unknown displaying:
displaying := 0;
fi
% \end{macrocode}
% Trong *exbase.mf*, macro *ecchar* ���c ��nh ngh�a b�i *|let ecchar=\;|*.
% \begin{macrocode}
let vnchar = ecchar;
let cmchar = ecchar;
% \end{macrocode}
%
% Load |T5| |encoding| v� c�c macro ��nh ngh�a c�c h� ch� c�i, h� d�u.
% \begin{macrocode}
input vncode;
% \end{macrocode}
%
% \subsection{Test: Parameters}
%
% Parameter for |t5supp-encoding|.
% \begin{macrocode}
%<*t5supp>
% get_acc_pos := 1;
% gen_t5_supp := 1;
% if known get_acc_pos or known gen_t5_supp:
mag := 100.375;
% fi
%</t5supp>
% \end{macrocode}
%
% *(KTV,2003/11/02):*
% Vi�c ��t *|defaultfont:="Times-Roman"|* s� sinh ra l�i
% (kh�ng t�m th�y font |tfm|) t��ng �ng.
% Xem th�m trong \href{../doc/vnr_bug_fix.dvi}{vnr_bug_fix}.
%
% *(KTV,2003/11/13):*
% Ph�i d�ng *|prologues:=1|* m�i c� th� |merge| c�c output t�o b�i
% |MetaPost| b�ng |mpmergeps.py|.
% (Ch�a ki�m tra �i�u n�y v�i |mergemps.py|.)
% \begin{macrocode}
%<*test>
% show_labels := 1; % value passed in the `makefile'
% makeXbox := 0; % value passed in the `makefile'
defaultscale := 1;
prologues := 1;
%defaultfont := "Times-Roman";
if known black_proof:
proofcolor := .9999[white, black];
else:
proofcolor := .3[white, black];
fi
if known gensize:
mag := 20/gensize;
else: mag := 2; fi
if known no_labels:
def penlabels(text _list) = enddef;
fi
%</test>
% \end{macrocode}
%
% \subsection{Test: Letters}
%
% Danh s�ch c�c ch� c�i ���c v� khi trong \tstmode.
% Mu�n |test| ch� c�i n�o th� ch� vi�c b� d�u |%| � tr��c ch� ��.
% C� th� th�c hi�n c�c ph�p g�n, v� d�: *|test_grave:=1|*.
% \emph{L�u �:} nh�ng ch� c�i ���c test s� g�m c� ch� hoa l�n ch� th��ng.
% (Xem ��nh ngh�a c�a *grave_fam*, *acute_fam*,... � \lref{def:accent_fam},
% ��nh ngh�a c�a *a_fam*, *d_fam*,... � \lref{def:letter_fam}.)
%
% \begin{multicols}3
% \begin{macrocode}
%<*test>
def testchars =
%<=def:testchars>
if known test_grave:
grave_fam(,)
fi if known test_acute:
acute_fam(,)
fi if known test_tilde:
tilde_fam(,)
fi if known test_hook:
hook_fam(,)
fi if known test_dot:
dot_fam(,)
fi if known test_a:
a_fam(,)
fi if known test_e:
e_fam(,)
fi if known test_i:
i_fam(,)
fi if known test_o:
o_fam(,)
fi if known test_u:
u_fam(,)
fi if known test_uhorn:
uhorn_fam(,)
fi if known test_y:
y_fam(,)
fi if known test_d:
d_fam(,)
fi if known test_all_chars:
full_fam(,)
fi
% a.acute_,
% a.dot_,
% a.grave_,
% a.hook_,
% a.tilde_,
% a.breve_,
% a.breve_.acute_,
% a.breve_.dot_,
% a.breve_.grave_,
% a.breve_.hook_,
% a.breve_.tilde_,
% a.circumflex_,
% a.circumflex_.acute_,
% a.circumflex_.dot_,
% a.circumflex_.grave_,
% a.circumflex_.hook_,
% a.circumflex_.tilde_,
% d.bar_,
% e.acute_,
% e.dot_,
% e.grave_,
% e.hook_,
% e.tilde_,
% e.circumflex_,
% e.circumflex_.acute_,
% e.circumflex_.dot_,
% e.circumflex_.grave_,
% e.circumflex_.hook_,
% e.circumflex_.tilde_,
% i.acute_,
% i.dot_,
% i.grave_,
% i.hook_,
% i.tilde_,
% o.acute_,
% o.dot_,
% o.grave_,
% o.hook_,
% o.tilde_,
% o.circumflex_,
% o.circumflex_.acute_,
% o.circumflex_.dot_,
% o.circumflex_.grave_,
% o.circumflex_.hook_,
% o.circumflex_.tilde_,
% o.horn_,
% o.horn_.acute_,
% o.horn_.dot_,
% o.horn_.grave_,
% o.horn_.hook_,
% o.horn_.tilde_,
% u.acute_,
% u.dot_,
% u.grave_,
% u.hook_,
% u.tilde_,
% u.horn_,
% u.horn_.acute_,
% u.horn_.dot_,
% u.horn_.grave_,
% u.horn_.hook_,
% u.horn_.tilde_,
% y.acute_,
% y.dot_,
% y.grave_,
% y.hook_,
% y.tilde_,
last
enddef;
%</test>
% \end{macrocode}
% \end{multicols}
%
% \danger
% Ta th�m v�o danh s�ch tr�n ch� c�i �o |last|. \emph{M�c ��ch:}
% Khi d�ng v�ng l�p |for| �� duy�t qua danh s�ch
% |testchars|, ta ph�i bi�t l�c n�o th� k�t th�c danh s�ch.
% Ch� c�i �o |last| t�o �i�u ki�n �� ki�m tra.
% Nh� v�y, |last| ph�i lu�n ���c |test|:
% ta kh�ng ���c ph�p b� �i |last| trong danh s�ch n�i tr�n.
% \endanger
%
% \begin{macrocode}
%<test> C.l.last := C.u.last := 256;
% \end{macrocode}
%
% \subsection{Test: Macros}
%
% \begin{macro}{used_char}
% Macro n�y ki�m tra xem \meta{char} v�i m� |_code| c� n�m trong
% danh s�ch |testchars| hay kh�ng. N�u c�, \meta{char} n�y s� ���c v�.
% Ch� trong \tstmode\ m�i c� s� ki�m tra n�y, c�n trong b�n
% \meta{publish} c�a |VNR-METAFONT| th� macro |used_char| ���c b� qua.
% Xem ��nh ngh�a c�a macro |define_vnchar| (\lref{def:define_vnchar}).
% \begin{macrocode}
%<*test>
vardef used_char(expr _code) =
%<=def:used_char>
boolean _is_used;
if not known test_all_chars:
_is_used := false;
forsuffixes $ = testchars:
if _code = vn_code($):
_is_used := true;
fi;
endfor;
else:
_is_used := true;
fi;
_is_used
enddef;
%</test>
% \end{macrocode}
% \end{macro}
%
% Khai b�o 14 bi�n ki�u |BOOLEAN|.
% C�c bi�n n�y ���c g�n gi� tr� ban ��u |FALSE|.
%
% \emph{V� d�:} bi�n |a_fam_used| c� gi� tr� |TRUE| n�u m�t trong c�c
% ch� c�i |a|, |�|, |�|, |�|, |�|, |�| ���c |test|. L�u � r�ng,
% c�c ch� c�i |a|, |�|, |�|, |�|, |�|, |�| ���c v� theo c�ch \emph{t��ng
% t�} nhau, n�n ta ch� c�n \emph{d�ng m�t bi�n} l� |a_fam_used|:
% n�u |a_fam_used| b�ng |TRUE|, th� ta s� |load| m� |MF| �� v� c�c
% ch� |a|, m� n�y ��t trong |vnlar|.
%
% Xem th�m ��nh ngh�a c�a |input_lr_fam|, |input_ur_fam| b�n d��i.
%
% \begin{macrocode}
%<*test>
forsuffixes _u =
A_fam_used, D_fam_used, E_fam_used, I_fam_used,
O_fam_used, U_fam_used, Y_fam_used,
a_fam_used, d_fam_used, e_fam_used, i_fam_used,
o_fam_used, u_fam_used, y_fam_used:
boolean _u;
_u := false;
endfor;
%</test>
% \end{macrocode}
%
% Gi� s� trong |test_char|, \meta{char} c� m� |_c| ���c \meta{test}.
% Khi ��, ta s� t�m xem \meta{char} n�y n�m trong h� n�o (|A_fam|,
% |e_fam|, v.v...). N�u (v� d�) n� n�m trong h� |a_fam|, th� ta s� g�n
% bi�n |a_fam_used| gi� tr� |TRUE|.
%
% \begin{macro}{test_fam}
%
% Macro |test_fam| d��i ��y c� nhi�m
% v� tr� l�i xem \meta{char} v�i m� |_c| c� n�m trong h� |_f| hay kh�ng;
% n�u c� th� g�n |_u| b�ng |TRUE|. \emph{L�u �:} c�c \meta{char} (ti�ng
% Vi�t) ch� c� m� ho�c nh� h�n |32|, ho�c l�n h�n |127|.
%
% \begin{macrocode}
%<*test>
def test_fam(text _f, _u, _c) =
n_ := 0;
if not _u:
forsuffixes $ = _f(,) 257:
n_ := n_ + 1;
if (($ < 32) or ($ > 127)) and ($ = C.u._c) or ($ = C.l._c):
_u := true;
fi
endfor
fi
enddef;
%</test>
% \end{macrocode}
% \end{macro}
%
% B�y gi�, ta duy�t qua t�t c� c�c h� (ch� hoa) �� xem |_c| thu�c h� n�o.
% R� r�ng, m�i \meta{char} ch� thu�c m�t v� ch� m�t h� m� th�i, n�n ta c�
% th� c�i thi�n vi�c duy�t b�ng c�ch d�ng |if...elif...if|. (Nh�ng vi�c
% n�y kh�ng \emph{kinh t�}l�m.)
%
% \begin{multicols}2
% \begin{macrocode}
%<*test>
forsuffixes _c = testchars:
test_fam(A_fam)(A_fam_used)(_c);
test_fam(D_fam)(D_fam_used)(_c);
test_fam(E_fam)(E_fam_used)(_c);
test_fam(I_fam)(I_fam_used)(_c);
test_fam(O_fam)(O_fam_used)(_c);
test_fam(U_fam)(U_fam_used)(_c);
test_fam(Y_fam)(Y_fam_used)(_c);
test_fam(a_fam)(a_fam_used)(_c);
test_fam(d_fam)(d_fam_used)(_c);
test_fam(e_fam)(e_fam_used)(_c);
test_fam(i_fam)(i_fam_used)(_c);
test_fam(o_fam)(o_fam_used)(_c);
test_fam(u_fam)(u_fam_used)(_c);
test_fam(y_fam)(y_fam_used)(_c);
test_fam(U_horn_fam)(U_fam_used)(_c);
test_fam(u_horn_fam)(u_fam_used)(_c);
endfor
%</test>
% \end{macrocode}
% \end{multicols}
%
% Bi�n |inpustr| ���c d�ng trong 4 macro s�p t�i.
%
% \begin{macrocode}
%<test>string inputstr;
% \end{macrocode}
%
% \begin{macro}{input_ur_fam}
% Xem h� ch� n�o ���c d�ng th� |load| m� |MF| �� v� h� t��ng �ng.
% \up � ��y l� h� c�c ch� hoa.
% \begin{macrocode}
%<*test>
def input_ur_fam =
inputstr := "";
if A_fam_used: inputstr := inputstr & "input vnuar; "; fi
if D_fam_used: inputstr := inputstr & "input vnudr; "; fi
if E_fam_used: inputstr := inputstr & "input vnuer; "; fi
if I_fam_used: inputstr := inputstr & "input vnuir; "; fi
if O_fam_used: inputstr := inputstr & "input vnuor; "; fi
if U_fam_used: inputstr := inputstr & "input vnuur; "; fi
if Y_fam_used: inputstr := inputstr & "input vnuyr; "; fi
scantokens(inputstr);
enddef;
%</test>
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{input_lr_fam}
% |Load| m� v� c�c ch� th��ng.
% \begin{macrocode}
%<*test>
def input_lr_fam =
inputstr := "";
if a_fam_used: inputstr := inputstr & "input vnlar; "; fi
if d_fam_used: inputstr := inputstr & "input vnldr; "; fi
if e_fam_used: inputstr := inputstr & "input vnler; "; fi
if i_fam_used: inputstr := inputstr & "input vnlir; "; fi
if o_fam_used: inputstr := inputstr & "input vnlor; "; fi
if u_fam_used: inputstr := inputstr & "input vnlur; "; fi
if y_fam_used: inputstr := inputstr & "input vnlyr; "; fi
scantokens(inputstr);
enddef;
%</test>
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{input_sc_fam}
% |Load| m� v� c�c ch� |small-cap|.
% \begin{macrocode}
%<*test>
def input_sc_fam =
inputstr := "";
if a_fam_used: inputstr := inputstr & "input vnuar; "; fi
if d_fam_used: inputstr := inputstr & "input vnudr; "; fi
if e_fam_used: inputstr := inputstr & "input vnuer; "; fi
if i_fam_used: inputstr := inputstr & "input vnuir; "; fi
if o_fam_used: inputstr := inputstr & "input vnuor; "; fi
if u_fam_used: inputstr := inputstr & "input vnuur; "; fi
if y_fam_used: inputstr := inputstr & "input vnuyr; "; fi
scantokens(inputstr);
enddef;
%</test>
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{input_li_fam}
% |Load| m� v� c�c ch� nghi�ng.
% \begin{macrocode}
%<*test>
def input_li_fam =
inputstr := "";
if a_fam_used: inputstr := inputstr & "input vnlai; "; fi
if d_fam_used: inputstr := inputstr & "input vnldi; "; fi
if e_fam_used: inputstr := inputstr & "input vnlei; "; fi
if i_fam_used: inputstr := inputstr & "input vnlii; "; fi
if o_fam_used: inputstr := inputstr & "input vnloi; "; fi
if u_fam_used: inputstr := inputstr & "input vnlui; "; fi
if y_fam_used: inputstr := inputstr & "input vnlyi; "; fi
scantokens(inputstr);
enddef;
%</test>
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{bboxcolor}
% \begin{macro}{bbxorule}
% Macro |bboxrule| d�ng �� v� �o�n th�ng n�i hai �i�m |w| v� |z|,
% v�i m�u l� |bboxcolor| v� ki�u ���ng th�ng l� |linecap|.
% \emph{L�u �:} |linecap| l� bi�n |internal| c�a |MetaPOST|.
%
% \danger
% N�u ta mu�n t�m th�i qu�n �i gi� tr� c�a m�t bi�n |internal|, � ��y l�
% bi�n |linecap|, th� d�ng |interim| trong m�t |group|. Sau |group| ��,
% gi� tr� c� c�a bi�n |internal| s� ���c ph�c h�i. ��i v�i bi�n |external|,
% ta d�ng h�m |save| thay v� |interim|.
% \endanger
% \begin{macrocode}
%<*test>
def bboxcolor = red enddef;
def bboxrule(expr w,z) =
begingroup
interim linecap := squared;
draw w..z
withpen pencircle scaled (.4/bp_per_pixel)
withcolor bboxcolor;
endgroup
enddef;
%</test>
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{makebbox}
% V� b�n c�nh c�a h�nh ch� nh�t bao quanh \meta{h�nh v�}
% v�i k�ch th��c c�a h�nh ch� nh�t b�ng k�ch th��c c�a \meta{h�nh v�}.
% \meta{H�nh v�} � ��y l� \meta{char} ho�c \meta{accent}.
% \begin{macrocode}
%<*test>
def makebbox(text rule) =
if known makeXbox:
for x = 0,w:
bboxrule((x,-d),(x,h)); endfor
for y = 0,h,-d:
bboxrule((0,y),(w,y)); endfor
fi
enddef;
%</test>
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{makebox}
% V� l��i g�m c�c �o�n th�ng �i qua c�c �i�m ��c bi�t.
% \danger
% Macro n�y d�ng �� k�t th�c vi�c v� \meta{char},
% kh�ng d�ng �� k�t th�c vi�c v� \meta{accent}.\\
% C� th� xem ch� th�ch v� macro n�y trong \mfb E/309/.
% \endanger
% \begin{macrocode}
%<*test>
def makebox(text rule) =
% \end{macrocode}
% V� b�y (7) ���ng th�ng n�m ngang: m�t ���ng �i qua g�c t�a ��;
% m�t ���ng �i � �� s�u |body_depth| -- ���ng n�y kh�ng th� th�y ���c
% n�u ta xem k�t qu� do vi�c |merge| c�c file "PS" t�o b�i "MetaPost".
% \begin{macrocode}
for y = 0, (cap_height+acc_height),
asc_height, body_height, x_height,
bar_height, desc_depth ,-body_depth:
rule((l,y),(r,y));
endfor
% \end{macrocode}
% \begin{macrocode}
for y = -3.5pt, 8.5pt, (x_height + acc_height):
rule((l-4pt,y),(l-2pt,y));
endfor
% \end{macrocode}
% V� c�c ���ng th�ng ��ng.
% \begin{macrocode}
for x=l,r:
rule((x,-body_depth),(x,body_height));
endfor
% \end{macrocode}
% V� c�c ���ng th�ng ��ng ph�.
% \begin{macrocode}
for x = u*(1 + floor(l/u)) step u until r-1:
rule((x,-body_depth),(x,body_height));
endfor
for x = 0.5w:
rule((x,-body_depth - 1pt),
(x,-body_depth - 1.5pt));
rule((x, cap_height + acc_height + 1pt),
(x, cap_height + acc_height + 1.5pt));
endfor
% \end{macrocode}
% V� th�m ���ng th�ng ��ng n�u |charic <> 0|.
% \begin{macrocode}
if charic <> 0:
rule((r + charic*pt, h.o_),
(r + charic*pt,.5h.o_));
fi
enddef;
%</test>
% \end{macrocode}
% \end{macro}
%
% \subsection{Test: enchar}
%
% \begin{macro}{endchar}
% Sau khi k�t th�c vi�c v� m�t \meta{char},
% ta v� h�nh ch� nh�t bao quanh \meta{char} �� (b�ng |makebbox|),
% v� v� l��i g�m c�c ���ng th�ng ��c bi�t (b�ng |makebox|).
%
% \danger
% Xem trong |METAFONTBook| v� |proofrule|.
% \endanger
% \begin{macrocode}
%<*test>
def endchar =
scantokens extra_endchar;
% if proofing > 0:
if known makeXbox:
makebox(proofrule);
makebbox(proofrule);
fi
shipit;
endgroup
enddef;
%</test>
% \end{macrocode}
% \end{macro}
%
% \subsection{Writting Shifting Information}
%
% \begin{macro}{abs_round}
% \begin{macrocode}
%<*t5supp>
def abs_round(expr _e) =
if _e < 0: ceiling(_e - .5)
else: floor(_e + .5)
fi
enddef;
%</t5supp>
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{write_shift_xy}
% Ghi ra *log* file th�ng tin v� |shift|; c�c th�ng tin n�y ���c s� d�ng
% trong qu� tr�nh chuy�n font *VNR* sang *type1* format.
% Xem \href{../doc/vnr_type1.pdf}{vnr_type1.pdf} (appendix {\bf A})
% �� bi�t th�m vai tr� c�a macro n�y.
% \begin{macrocode}
%<*t5supp>
def write_shift_xy(suffix _l, _a)(expr _sx, _sy) =
if known bp_per_pixel:
message "CC " &
if case_ = capital: "capital"
elseif case_ = small: "small"
else: "smallcap"
fi & " " & str _l & " " & str _a & " " &
decimal(abs_round(_sx*bp_per_pixel*10/designsize)) & " " &
decimal(abs_round(_sy*bp_per_pixel*10/designsize));
fi
enddef;
%</t5supp>
% \end{macrocode}
% \end{macro}
%
% \subsection{Miscellanea}
%
% Bi�n |case_| d�ng l�m |switch| �� x�c ��nh ki�u ch� hoa/th��ng/...
% \begin{macrocode}
numeric case_;
small := 0;
capital := 1;
smallcap := 2;
def set_lowercase =
case_ := small;
def vncase = l enddef;
enddef;
def set_uppercase =
case_ := capital;
def vncase = u enddef;
enddef;
def set_smallcap =
case_ := smallcap;
def vncase = l enddef;
enddef;
% \end{macrocode}
%
% \begin{macro}{casename}
% T�n ��y �� c�a ch� c�i �ang ���c
% |METAFONT| v� (ch� khi |testing| l� \emph{unknown}).
% C� th� th�y c�c t�n n�y tr�n |terminal| v� trong file |log|
% n�u ch�y |mf| v�i |mode := proof|.
% \begin{macrocode}
def casename expr _name =
%<*!test>
"The " &
if case_ = capital: "capital"
elseif case_ = small: "small"
else: "smallcap" fi
& " letter " & _name
%</!test>
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{ifknown}
% This macro expands to |_b| if the suffix |_a| is \emph{unknown},
% and to |_a| itself in the other case.
% Macro n�y ���c d�ng nhi�u, khi ph�i l�a ch�n c�c bi�n t��ng �ng
% v�i c�c d�u. Xem m�t v� d� � \lref{use:ifknown}.
% \begin{macrocode}
def ifknown(suffix _a)(expr _b) =
if known _a: _a else: _b fi
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{tand}
% H�m t�nh |tangent| c�a g�c |d| (t�nh b�ng ��, |d = degree|).
% \begin{macrocode}
def tand(expr _d) =
(sind(_d)/cosd(_d))
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{hp}
% L�m tr�n theo chi�u ngang (|horizontal|).
% \begin{macrocode}
def hp(expr _x) =
hround(_x*hppp)
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{vp}
% L�m tr�n theo chi�u ��ng (|vertical|).
% \begin{macrocode}
def vp(expr _y) =
vround(_y*vppp)
enddef;
% \end{macrocode}
% \end{macro}
%
% \subsection{Macro: begin, end}
%
% \begin{macro}{begin_pic}
% \begin{macrocode}
def begin_pic(suffix _n) =
begingroup
clearxy;
clearit;
clearpen;
picture vn.vncase._n.pic;
vn.vncase._n.pic :=
begingroup
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{end_pic}
% \begin{macrocode}
def end_pic =
% \end{macrocode}
%
% \danger
% Ta ch� c� th� d�ng |makebbox| � ��y m� th�i!
% \endanger
%
% \begin{macrocode}
%<test> makebbox(proofrule);
% \end{macrocode}
%
% \begin{macrocode}
currentpicture
endgroup;
endgroup
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macrocode}
let end_accent = end_pic;
let begin_letter = begin_pic;
let end_letter = end_pic;
% \end{macrocode}
%
% \begin{macro}{begin_accent}
% \begin{macrocode}
def begin_accent(suffix _a) =
begin_pic(_a);
set_char_dimens(vn_width(_a), vn_height(_a), 0)
enddef;
% \end{macrocode}
% \end{macro}
%
% \subsection{Picture's Properties}
%
% T� \meta{h�nh v�} d�ng �� ch� \meta{picture} do |METAFONT|
% t�o ra khi v� ch� c�i \meta{char}, ho�c d�u \meta{accent}.
% M�i \meta{h�nh v�} c� c�c thu�c t�nh sau ��y:
% \begin{verbatim}
% code, pic, width, height, top, bot, depth,
% ic, left, right, gap, join_xp, join_x
% \end{verbatim}
%
% \begin{multicols}2
% \begin{macrocode}
def vn_code(suffix _n) =
C.vncase._n
enddef;
def vn_pic(suffix _n) =
vn.vncase._n.pic
enddef;
def vn_width(suffix _n) =
vn.vncase._n.w#
enddef;
def vn_height(suffix _n) =
vn.vncase._n.h#
enddef;
def vn_top(suffix _n) =
vn.vncase._n.top#
enddef;
def vn_depth(suffix _n) =
vn.vncase._n.d#
enddef;
def vn_bot(suffix _n) =
vn.vncase._n.bot#
enddef;
def vn_ic(suffix _n) =
vn.vncase._n.ic#
enddef;
def vn_left_adj(suffix _n) =
vn.vncase._n.left_adj#
enddef;
def vn_right_adj(suffix _n) =
vn.vncase._n.right_adj#
enddef;
def vn_gap(suffix _n) =
vn.vncase._n.gap#
enddef;
def vn_join_xp(suffix _n) =
vn.vncase._n.join.x
enddef;
def vn_join_x(suffix _n) =
vn.vncase._n.join.x#
enddef;
def vn_rt(suffix _n) =
vn.vncase._n.rt#
enddef;
def vn_dot_shift_y(suffix _n) =
vn.vncase._n.dot_shift.y#
enddef;
def vn_ac_top =
vn.vncase.accent_top#
enddef;
def vn_double_ac_top =
vn.vncase.double_accent_top#
enddef;
let vn_left_side = vn_join_x;
def vn_right_side(suffix _a) =
(vn_width(_a) - vn_left_side(_a))
enddef;
def align_left(suffix _a, _b) =
0
enddef;
def vn_align_join(suffix _a, _b) =
(vn_join_x(_a) - vn_join_x(_b))
enddef;
def vn_align_right(suffix _a, _b) =
(vn_width(_a) - vn_width(_b))
enddef;
% \end{macrocode}
% \end{multicols}
%
% \subsection{Setting Macros}
%
% \begin{macro}{define_accent_dimens}
% X�c ��nh c�c k�ch th��c c�a m�t d�u (g�m c� |width|, |height|, |top|).
% \begin{macrocode}
def define_accent_dimens(suffix _a)(expr _w, _h) =
vn_width(_a) := _w;
vn_height(_a) := _h;
vn_top(_a) := vn_height(_a) + vn_letter_height# + vn_accent_gap#;
% \end{macrocode}
% T�nh l�i gi� tr� l�n nh�t c�a |vn_max_ac_top#|.
% \begin{macrocode}
vn_max_ac_top# := max(vn_max_ac_top#, vn_top(_a));
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{set_char_dimens}
% \begin{macrocode}
def set_char_dimens(expr _w, _h, _d) =
charwd := _w;
charht := _h;
chardp := _d;
w := hp(charwd);
h := vp(charht);
d := vp(chardp);
charic := 0;
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{set_letter_dimens}
% \begin{macrocode}
def set_letter_dimens(suffix _l)(expr _w, _h, _d, _ic, _lft, _rt) =
set_char_dimens(_w, _h, _d);
vn_width(_l) := _w;
vn_height(_l) := _h;
vn_depth(_l) := _d;
vn_ic(_l) := _ic;
vn_left_adj(_l) := _lft;
vn_right_adj(_l) := _rt;
adjust_fit(_lft, _rt);
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{set_ac_join}
% \begin{macrocode}
def set_ac_join(suffix _a)(expr _xp, _x, _rt) =
vn_join_xp(_a) := _xp;
vn_join_x(_a) := _x;
vn_rt(_a) := _rt;
%<*test>
if known show_labels:
makelabel("j", (vn_join_xp(_a), 0));
makelabel("J", (hp(vn_join_x(_a)), 0));
makelabel("r", (hp(vn_width(_a)), vp(vn_rt(_a))));
makelabel("o", (0,0));
fi;
%</test>
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{set_letter_join}
% \begin{macrocode}
def set_letter_join(suffix _l)(expr _xp, _x) =
vn_join_xp(_l) := _xp;
vn_join_x(_l) := _x;
%<*test>
if known show_labels:
makelabel("X", (vn_join_xp(_l), vp(vn_height(_l))));
makelabel("Y", (hp(vn_join_x(_l)), vp(vn_height(_l))));
fi;
%</test>
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{set_adj_gap}
% \begin{macrocode}
def set_adj_gap(suffix _l, _a) =
%<=use:ifknown>
adj_gap# := ifknown(vn_gap(_l._a),
ifknown(vn_gap(_a), 0));
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{set_shift}
% \begin{macrocode}
def set_shift(suffix _l, _a) =
shift.y := vp(vn_top(_a) - vn_height(_a))
+ ifknown(hook_shift.y._l._a,0)*u;
shift.x := get_join_xp(_l, _a) - vn_join_xp(_a)
+ slant*shift.y
+ ifknown(hook_shift.x.vncase._l._a,0)*u;
% \end{macrocode}
%
% \begin{macrocode}
shift.y# := vn_top(_a) - vn_height(_a)
+ ifknown(hook_shift.y._l._a#,0)*u#;
shift.x# := get_join_x(_l, _a) - vn_join_x(_a)
+ slant*shift.y#
+ ifknown(hook_shift.x.vncase._l._a#,0)*u#;
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{set_ic}
% \begin{macrocode}
def set_ic(suffix _l, _a) =
italcorr max(vn_ic(_l),
vn_width(_a) + shift.x#
+ slant*(vn_rt(_a) + shift.y#)
- w# + .5u#);
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{set_lic}
% \begin{macrocode}
def set_lic(suffix _l) =
italcorr vn_ic(_l);
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{set_fit}
% \begin{macrocode}
def set_fit(suffix _l) =
adjust_fit(vn_left_adj(_l), vn_right_adj(_l));
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{set_dot_shift}
% to avoid error when calling |set_dot_shift(idot)|
% \begin{macrocode}
C.l.idot.dot_ = C.u.idot.dot_ = 256;
% \end{macrocode}
%
% \begin{macrocode}
def set_dot_shift(suffix _l) =
shift.y := - vp(ifknown(vn_dot_shift_y(_l), vn_bot(dot_)));
shift.x := get_join_xp(_l, dot_) - vn_join_xp(dot_) + slant*shift.y;
enddef;
% \end{macrocode}
% \end{macro}
%
% \subsection{Getting Macros}
%
% \begin{macro}{get_join_xp}
% \begin{macrocode}
def get_join_xp(suffix _l, _a) =
ifknown(vn_join_xp(_l._a), vn_join_xp(_l))
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{get_join_x}
% \begin{macrocode}
def get_join_x(suffix _l, _a) =
ifknown(vn_join_x(_l._a), vn_join_x(_l))
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{get_top}
% \begin{macrocode}
def get_top(suffix _a) =
%<=def:get_top>
max(vn_top(_a) + adj_gap#,
if vn_top(_a) <= vn_ac_top:
vn_ac_top
else:
vn_double_ac_top
fi)
enddef;
% \end{macrocode}
% \end{macro}
%
% \subsection{Pos Function}
%
% \begin{macro}{pos}
% Xem ch� th�ch trong \mfb E/310/.
% \begin{macrocode}
vardef pos@#(expr b,d) =
if known b:
if b <= currentbreadth:
(x@#r - x@#l, y@#r - y@#l) = (eps,0) rotated d;
else: (x@#r - x@#l, y@#r - y@#l) = (b - currentbreadth, 0) rotated d;
fi
else: (x@#r - x@#l, y@#r - y@#l) = (b - currentbreadth, 0) rotated d;
fi
% \end{macrocode}
% H�nh nh� anh Th�nh nh�m l�n, khi d�ng *|if known b ... else|*?
% Kh�ng! Quan s�t file *log* (sau khi th�m *message ...* v�o trong *else:*)
% ta th�y c� nhi�u l�n tr��ng h�p "else" x�y ra... Xem x�t m�t s� tr��ng h�p
% g�i *pos*, ta th�y: c� khi *|expr b|* l� m�t bi�u th�c,
% c� khi n� l� m�t bi�n. V� d�, khi v� *tilde* trong *vnaccent*,
% anh Th�nh �� d�ng\\\centerline{"pos1(vn_tilde_vair, theta + 90)"}
% Nh� v�y l�, h�m *pos* ���c ��nh ngh�a � ��y \emph{r�t m�nh}.
% M�t c�u h�i ��t ra l�, li�u c� c�n ph�n bi�t hai tr��ng h�p nh� tr�n?
% C�u tr� l�i l� \emph{kh�ng ��nh}.
% \up � c�a anh Th�nh l�: n�u *|expr b|* ���c d�ng l� m�t bi�n, th� c�n
% ph�i kh�ng ch� tr��ng h�p gi� tr� c�a bi�n �� � d��i ng��ng cho ph�p!
% \begin{macrocode}
x@# = .5(x@#l + x@#r);
y@# = .5(y@#l + y@#r)
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{vn_sl_shift}
% \begin{macrocode}
def vn_sl_shift(suffix _a) =
% .5slant*(adj_y# + vn_height(_a))
0
enddef;
% \end{macrocode}
% \end{macro}
%
% \subsection{Drawing Letters and Accents}
%
% \begin{macro}{define_vnchar}
% \label{def:define_vnchar}
%
% Macro n�y n�i d�u |_c| v�i ch� |_c|, t�o th�nh m�t ch� c�i
% ti�ng Vi�t. V� d�, n�i d�u huy�n v�i ch� "a".
%
% \begin{macrocode}
def define_vnchar(suffix _l, _a) =
%<=def:define_vnchar>
%<test> if used_char(vn_code(_l._a)):
set_adj_gap(_l, _a);
beginchar(vn_code(_l._a),
vn_width(_l),
get_top(_a),
vn_depth(_l));
set_shift(_l, _a);
set_ic(_l, _a);
set_fit(_l);
currentpicture := vn_pic(_l);
addto currentpicture also vn_pic(_a)
shifted (shift.x, shift.y + vp(adj_gap#));
%<*t5supp>
write_shift_xy(_l, _a)
(shift.x + hp(vn_left_adj(_l)) + letter_fit,
shift.y + vp(adj_gap#));
%</t5supp>
endchar
%<test> fi
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{define_double_accent}
% \begin{macrocode}
def define_double_accent(suffix _a, _b)(expr _adj_x, _adj_y) =
shift.y# := _adj_y + vn_height(_a);
shift.x# := _adj_x + slant*shift.y#;
define_accent_dimens(_a._b, vn_width(_a), vn_height(_b) + shift.y#);
begin_accent(_a._b);
currentpicture := vn_pic(_a);
addto currentpicture
also vn_pic(_b) shifted (hp(shift.x#), vp(shift.y#));
%<*t5supp>
write_shift_xy(_a, _b)(hp(shift.x#), vp(shift.y#));
%</t5supp>
set_ac_join(
_a._b,
vn_join_xp(_a),
vn_join_x(_a),
if vn_width(_a) + slant*vn_rt(_a)
> vn_width(_b) + shift.x#
+ slant*(vn_rt(_b) + shift.y#):
vn_rt(_a)
else:
vn_rt(_b) + shift.y#
fi);
end_accent;
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{define_vnaccent}
%
% V� \meta{accent} |_a| v�i m� |_c|.
% Ch� d�ng v�i |T5supp|.
% Xem c�ch d�ng trong *vnuacc* \lref{use:define_vnaccent}.
%
% \begin{macrocode}
%<*t5supp>
def define_vnaccent(expr _c)(suffix _a) =
%<=def:define_vnaccent>
beginchar(_c, vn_width(_a), vn_height(_a), 0);
currentpicture := vn_pic(_a);
endchar
enddef;
%</t5supp>
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{define_vnchar_dot}
%
% Th�m d�u n�ng v�o m�t ch�
%
% \begin{macrocode}
def define_vnchar_dot(suffix _l) =
%<test> if used_char(vn_code(_l.dot_)):
% \end{macrocode}
% Ta ph�n bi�t hai tr��ng h�p: ch� |�| (th��ng)
% v� c�c ch� kh�c (v�i d�u n�ng).
% \begin{macrocode}
if (case_ = small) and (vn_code(_l.dot_) = vn_code(i.dot_)):
beginchar(vn_code(i.dot_),
vn_width(idot),
vn_height(idot),
vn_bot(dot_));
set_dot_shift(idot);
set_lic(idot);
set_fit(idot);
currentpicture := vn_pic(idot);
else:
beginchar(vn_code(_l.dot_),
vn_width(_l),
vn_height(_l),
ifknown(vn_depth(_l.dot_),
max(vn_bot(dot_), vn_depth(_l))));
set_dot_shift(_l);
set_lic(_l);
set_fit(_l);
currentpicture := vn_pic(_l);
fi
addto currentpicture
also vn_pic(dot_) shifted (shift.x, shift.y);
%<*t5supp>
write_shift_xy(_l, dot_)
(shift.x + hp(vn_left_adj(_l)) + letter_fit,
shift.y);
%</t5supp>
endchar
%<test> fi
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{define_vnchar_dot_ac}
%
% Th�m d�u v� d�u n�ng v�o m�t ch� c� d�u.
%
% \begin{macrocode}
def define_vnchar_dot_ac(suffix _l, _a) =
%<test> if used_char(vn_code(_l._a.dot_)):
set_adj_gap(_l, _a);
beginchar(vn_code(_l._a.dot_),
vn_width(_l),
get_top(_a),
max(vn_bot(dot_), vn_depth(_l)));
set_shift(_l, _a);
set_ic(_l, _a);
set_fit(_l);
currentpicture := vn_pic(_l);
addto currentpicture
also vn_pic(_a) shifted (shift.x, shift.y + vp(adj_gap#));
set_dot_shift(_l);
addto currentpicture
also vn_pic(dot_) shifted (shift.x, shift.y);
%<*t5supp>
write_shift_xy(_l._a, dot_)
(shift.x + hp(vn_left_adj(_l)) + letter_fit, shift.y);
%</t5supp>
endchar
%<test> fi
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{define_vnchar_horn}
%
% V� r�u cho ch� |u| ho�c |o|.
%
% \begin{macrocode}
def define_vnchar_horn(suffix _l) =
%<test> if used_char(vn_code(_l.horn_)):
select_horn(_l);
set_shift_horn(_l);
update_horn_width(_l);
beginchar(vn_code(_l.horn_),
updated_width#,
vn_top(cur_horn_),
vn_depth(_l));
set_ic(_l, cur_horn_);
set_fit(_l);
select_letter_u(_l);
addto currentpicture
also vn_pic(cur_horn_) shifted (shift.x, shift.y);
endchar
%<test> fi
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{select_horn}
%
% Ch�n r�u c�a ch� |u| hay ch� |o|.
%
% \begin{macrocode}
def select_horn(suffix _l) =
if vn_code(_l.horn_) = vn_code(u.horn_):
def cur_horn_ = uhorn_ enddef;
else: def cur_horn_ = ohorn_ enddef;
fi
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{update_horn_width}
% \begin{macrocode}
def update_horn_width(suffix _l) =
_du := (shift.x + hp(vn_width(cur_horn_)))
- (hp(vn_width(_l) + vn_left_adj(_l)
+ vn_right_adj(_l)) + 2letter_fit)
- slant*(shift.y + vp(vn_height(cur_horn_)));
updated_width# :=
vn_width(_l)
if _du > .5u:
+ .5u#*floor(_du/.5u)
fi
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{set_shift_horn}
% \begin{macrocode}
def set_shift_horn(suffix _l) =
shift.y := vp(vn_bot(cur_horn_));
shift.x := vn_join_xp(_l.horn_join)
- vn_join_xp(cur_horn_) + slant*(shift.y);
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{select_letter_u}
% \begin{macrocode}
def select_letter_u(suffix _l) =
% test for the serif capital u letter with horn
if serifs and (case_ <> small) and (vn_code(_l.horn_) = vn_code(u.horn_)):
% use the modified "U" (without right part of the right serif)
currentpicture := vn_pic(Uhorn)
else:
currentpicture := vn_pic(_l)
fi
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{define_vnchar_horn_ac}
% set |cur_horn_| to |uhorn_| or |ohorn_| according to |_l|.
% \begin{macrocode}
def define_vnchar_horn_ac(suffix _l, _a) =
%<test> if used_char(vn_code(_l.horn_._a)):
select_horn(_l);
set_adj_gap(_l, _a);
set_shift_horn(_l);
update_horn_width(_l);
beginchar(vn_code(_l.horn_._a),
updated_width#,
get_top(_a),
vn_depth(_l));
set_ic(_l, cur_horn_);
set_fit(_l);
select_letter_u(_l);
addto currentpicture also vn_pic(cur_horn_)
shifted (shift.x, shift.y);
set_shift(_l.horn_, _a);
% if serifs and (vn_code(_l.horn_._a) = vn_code(o.horn_.grave_)):
% shift.x := shift.x + max(0, u - .3stem);
% fi
set_ic(_l, _a);
addto currentpicture also vn_pic(_a)
shifted (shift.x, shift.y + vp(adj_gap#));
%<*t5supp>
write_shift_xy(_l.horn_, _a)
(shift.x + hp(vn_left_adj(_l)) + letter_fit,
shift.y + vp(adj_gap#));
%</t5supp>
endchar
%<test> fi
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{define_vnchar_horn}
% \begin{macrocode}
def define_vnchar_horn_dot(suffix _l) =
%<test> if used_char(vn_code(_l.horn_.dot_)):
select_horn(_l); % set cur_horn_ to uhorn_ or ohorn_ according to _l
set_shift_horn(_l);
update_horn_width(_l);
beginchar(vn_code(_l.horn_.dot_),
updated_width#,
vn_top(cur_horn_),
max(vn_bot(dot_), vn_depth(_l)));
set_ic(_l, cur_horn_);
set_fit(_l);
select_letter_u(_l);
addto currentpicture also vn_pic(cur_horn_)
shifted (shift.x, shift.y);
set_dot_shift(_l);
addto currentpicture also vn_pic(dot_)
shifted (shift.x, shift.y);
%<*t5supp>
write_shift_xy(_l.horn_, dot_)
(shift.x + hp(vn_left_adj(_l)) + letter_fit,
shift.y);
%</t5supp>
endchar
%<test> fi
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{hook_arck.r}
% |hook_arc| is based on |super_arc| from exbase.mf
% \begin{macrocode}
vardef hook_arc.r(suffix $, $$)(expr _superness, _swap) =
pair center, corner;
if (y$ = y$r) or _swap:
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;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{hook_arc.l}
% \begin{macrocode}
vardef hook_arc.l(suffix $, $$)(expr _superness, _swap) =
pair center, corner;
if (y$ = y$r) or _swap:
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;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{vn_hook_bulb}
% |vn_hook_bulb| is based on bulb from |exbase.mf|
% \begin{macrocode}
def vn_hook_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;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{vn_draw_horn}
% \begin{verbatim}
% ====4r===
% = 1 = z1r = z4r
% = = y2 = 1/3[y1, y3]
% = 4 22l
% = =
% = =
% ===4l====
% ==
% ==
% 3===
% \end{verbatim}
%
% \begin{macrocode}
def vn_draw_horn(suffix _a)(expr _dotsize, _horn_stem, _horn_bot_theta) =
cur_dotsize# := _dotsize;
cur_stem# := _horn_stem;
define_blacker_pixels(cur_dotsize, cur_stem);
% \end{macrocode}
% \begin{macrocode}
if not square_dots:
pickup crisp.nib;
pos4(cur_dotsize, 90);
top y4r = h;
x4 = w - .5cur_dotsize;
pos1(cur_stem, 90);
pos2(cur_stem, 0);
pos3(cur_stem, _horn_bot_theta - 90);
z1r = z4r;
rt x2r = hround(x4 + .5cur_dotsize) + 2eps;
lft x3l = 0;
bot y3r = 0;
y2 = 1/3[y1, y3];
y_ := ypart( (z1{right} ... z2{down} ... z3 )
intersectiontimes (z4l{right} .. {left}z4r) );
if y_ < 0:
y_ := 1;
fi
% \end{macrocode}
% V�i �o�n m� d��i ��y, ta t� ���c m�t n�a h�nh tr�n v� m�t tam gi�c cong
% c� m�t c�nh l� ���ng k�nh c�a n�a h�nh tr�n. Tam gi�c n�y ���c ch�n
% d�a tr�n tham s� |y_| � tr�n.
% {\ttfamily
% \begin{verbatim}
% ooooo
% ooooooox
% ooooooooxx
% oooooooooxxx
% oooooooooxxxx
% oooooooooxxxxx
% ooooooooxxxxxxx
% oooooooxxxxxx
% ooooooxxxxx
% ooooxxx
% \end{verbatim}
% }
% \begin{macrocode}
filldraw z4r{left}
.. subpath (0, y_) of (z4l{right}.. {left}z4r)
-- cycle;
% \end{macrocode}
% \danger
% Tuy nhi�n, v�i ph�n h�nh tr�n � tr�n, khi ���c ph�ng to, c�i r�u s�
% b� khuy�t m�t m�nh.
%
% �� kh�c ph�c l�i n�y, anh Th�nh �� th�m v�o m�t ch�t,
% |--z2--cycle|, trong �o�n m� tr�n. M�nh khuy�t b�y gi� kh�ng c�n.
% Tuy nhi�n, c�c font |typewriter| khi �� ��u b� l�i <<|strange path|>>.
% \emph{L�i n�y xu�t hi�n trong b� |VNR| ng�y 2003/03/03
% (\href{
http://vinux.sourceforge.net/vntex}{vinux.sourceforge.net/vntex}).}
% \endanger
%
% Ti�p theo, ta v� d�u ph�y, th�m v�o h�nh � tr�n �� t�o r�u.
% \begin{macrocode}
filldraw stroke
z1e{right} ... z2e{down} ... {left}z3e;
% \end{macrocode}
% �� che �i m�nh khuy�t ��ng th�i tr�nh l�i � tr�n,
% ta c� th� vi�t m� ri�ng... �� t�o m�t tam gi�c �� l�n.
% C�c ��nh c�a tam gi�c n�y l� c�c �i�m \meta{ngo�i c�ng} c�a r�u.
% Cho ��n ng�y "2003/11/30", mi�ng v� n�y ch�a th� hi�n thi�u s�t n�o.
% C�c font |typewriter| ��u t�t, nh�ng c�c font |csc| th� v�n\footnote{%
% �� kh�c ph�c l�i sau �� m�t ng�y, c�ng v�i vi�c vi�t l�i |docstrip|.
% \emph{Nguy�n nh�n:} c�c |guard| trong file
% *|vndriver.dtx|* l� c�c |nested| |guard|, v� |docstrip.py| khi ��
% kh�ng th� hi�u �i�u n�y.}...
% \danger
% C�n xem l�i |METAFONTbook|, xem th� tam gi�c n�y li�u c� ��nh *r�t nh�n*
% hay l� *tr�n* (nh� khi d�ng |draw|)? (\emph{Tr� l�i:} d�ng |filldraw|
% th� chuy�n n�y kh�i ph�i lo....)
% \endanger
% \begin{macrocode}
filldraw z1r--z2r--z4l--cycle;
% \end{macrocode}
% \begin{macrocode}
%<test> penlabels(0, 1, 2, 3, 4);
set_ac_join(_a, x3,
.5cur_stem*sind(_horn_bot_theta),
h# - .5cur_dotsize#);
% \end{macrocode}
% \begin{macrocode}
else:
pickup fine.nib;
pos4(cur_dotsize, 90);
top y4r = h;
x4 = w - .5cur_dotsize;
pos4'(cur_dotsize, 0);
z4' = z4;
dot(4', 4); % squarish dot
horn_join := max(fine.breadth, floor cur_stem);
horn_bot := max(fine.breadth, floor .8cur_stem);
pos0(horn_join, 0);
pos1(horn_join, 0);
pos2(horn_bot, 0);
y0 = y4;
y1 = y4l;
x0r = x1r = x4'r;
lft x2l = 0;
bot y2r = 0;
z2' = whatever[z1, z2];
numeric _vn_bot_width;
pos2'(_vn_bot_width, -90 + _horn_bot_theta);
z2l = z2'l;
filldraw stroke z0e -- z1e .. z2'e; % tail
%<test> penlabels(0, 1, 2', 3, 4);
set_ac_join(_a, x2', 0, h#);
fi
vn_bot(_a) := vn_top(_a) - vn_height(_a);
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{set_horn_join}
% \begin{macrocode}
def set_horn_join(suffix _l)(expr _pl, _pr) =
select_horn(_l); % set cur_horn_ to uhorn_ or ohorn_ according to _l
path bot_line;
pair L, R;
bot_line := (.5w, vp(vn_bot(cur_horn_))) -- (w, vp(vn_bot(cur_horn_)));
L := point xpart(bot_line intersectiontimes _pl) of bot_line;
R := point xpart(bot_line intersectiontimes _pr) of bot_line;
set_ac_join(_l.horn_join, xpart .5[L, R], 0, 0);
enddef;
% \end{macrocode}
% \end{macro}
%
% \subsection{Oct031 Character}
%
% \begin{macro}{lig_CGQ_table}
% \begin{macrocode}
def lig_CGQ_table(expr k) =
"C" kern k, "G" kern k, "Q" kern k
enddef;
% \end{macrocode}
%
% \begin{macrocode}
def end_ligtable = 0 kern 0 enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{input_lig}
% define input_lig to generate only char oct"031" from excspl.mf
% \begin{macrocode}
def input_lig suffix @# =
let save_endchar = endchar;
let endchar = lig_endchar;
scantokens("input " & str @#);
relax;
let endchar = save_endchar;
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{lig_endchar}
% \begin{macrocode}
def lig_endchar =
if charcode = oct"031":
save_endchar
else:
endgroup
fi
enddef;
% \end{macrocode}
% \end{macro}
%
% \subsection{Macro: generate}
%
% \begin{macro}{generate}
% File |vnr10.mf| s� |input| c�c file |vnbase.mf| v� |ecrm.mf|.
% ��n l��t m�nh, |ecrm| s� |input| driver l� |exroman| b�ng c�ch g�i
% *|generate exroman|* (��i v�i |ec|, |generate| ch�nh l� |input|).
% {\tiny
% \begin{verbatim}
% 0: 0 *
% 1: 1 +- vnr10.mf
% 2: 2 | +- vnbase.mf
% 3: 3 | | +- exbase.mf
% 4: 3 | | +- vncode.mf
% 5: 2 | +- ecrm.mf
% 6: 3 | | +- null.mf
% 7: 3 | | +- vnroman.mf
%
% (See |doc/vnr10_tree_*.txt| for full detail)
% \end{verbatim}
% }
% �� thay th� |exroman| b�ng |driver| c�a |VNR|, ta s� ��nh ngh�a l�i
% |generate|, nh� v�o ��c �i�m: c�c |driver| c�a |ec| ��u b�t ��u b�ng
% hai k� t� |ec|, v� c�c |driver| c�a |VNR| (bao g�m \emph{vnroman},
% \emph{vncsc}, \emph{vntextit}) ���c b�t ��u b�i |vn|.
%
% \danger
% Kh�ng th� hi�u t�i sao ph�i d�ng |scantokens("input null")|.
% N�u kh�ng c� d�ng n�y, th� t�t c� c�c file ��u ���c |input| m�t
% c�ch \emph{b�nh th��ng}, nh�ng kh�ng c� ch� n�o ���c v� c�.
%
% T�i sao anh Th�nh l�i c� th� ngh� ra chuy�n th�m d�ng n�y v�o?
% \emph{Qu� si�u!}
% \endanger
% \begin{macrocode}
vardef generate @# =
scantokens("input null");
scantokens("input vn" & substring(2, length(str @#)) of str @#);
enddef;
% \end{macrocode}
% \end{macro}
%
% \begin{macrocode}
%</vnbase>
% \end{macrocode}
% \endinput