% bzrsetup.mf: interesting and/or necessary things for bzrto's Metafont output.
% bzrbase.mf: more interesting and necessary things for bzrmf.awk's output
%	from the above Metafont file. --- koaunghi.un@zdv.uni-tuebingen.de
% 
% Copyright (C) 1992 Free Software Foundation, Inc.
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2, or (at your option)
% any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


% |true_design_size| must be set before this file is input.  It is
% supposed to be the design size of the original font.  If the user does
% not set |designsize| on the command line, we default to the following.
default_design_size# := 10pt#;
if designsize = 0: designsize := default_design_size#; fi;

% It's pointless to actually produce different TFM files for different
% design sizes: we have only one set of outlines, after all.  So we
% adjust the resolution to account for different sizes, by setting
% |mag|.  Then we reset |designsize| to the default.
if unknown mag: mag := 1; fi;
mag := mag * designsize / default_design_size#;

% So we can produce output at varying sizes, all our dimensions are
% output in terms of the ad hoc parameter |u|.
% 
u# := default_design_size# / true_design_size#;

designsize := default_design_size#;

% Macros from page 289 of {\sl The Metafontbook} for short-circuit evaluation.
% 
def cand (text q) = startif true q else: false fi enddef;
def cor (text q) = startif true true else: q fi enddef;
tertiarydef p startif true = if p: enddef;

% The proof resolution of 2601.72 pixels per inch established by plain
% \MF\ does not always work, because the characters might be too large
% (or small, for that matter) for the paper size.  So, here we change
% the proof resolution to fit the design size of the font into
% |proof_size| inches.  To do this, we must know the resolution of the
% device the proof output will be printed on; we make |proof_resolution|
% default to 300.
% 
if unknown mode cor ((mode = proof) or (mode = smoke)):
  % Given in inches:
  if unknown proof_size: proof_size := 7; fi;
  
  % Given in pixels per inch:
  if unknown proof_resolution: proof_resolution := 300; fi;
  
  % Set up the new mode to be the same as the old one, except for the
  % resolution.
  original_mode := if known mode: mode else: proof fi;
  mode_def bzr_proof_mode =
    if original_mode = proof:
      proof_;
    else:
      smoke_;
    fi;
    pixels_per_inch
      := (proof_size * proof_resolution)
         * (72.27 / proof_resolution)
         * (72.27 / designsize);
  enddef;
  mode := bzr_proof_mode;
fi;

% Set up the device values for this run.  Since we allow a nonstandard
% value of |proofing| (see below), we must save its value, if it has
% already been assigned.
%
if (known proofing) cand (proofing > 2):
  save_proofing := proofing;
fi

mode_setup;

if known save_proofing:
  proofing := save_proofing;
fi;


% We can't define the pixel-oriented version of |u| until after
% |mode_setup| has been called.
define_pixels (u);

% Use a font that blends better with the \MF\ logo for the title line.
% 
special "titlefont cmss8";

% If we are doing smoke proofs, put the character at its actual size on
% the output; if we're doing gray proofs, use a smaller font for the
% labels.
% 
if proofing <= 1:
  special "labelfont " & jobname;
  extra_beginchar := extra_beginchar &
    "makelabel.lft.nodot (decimal charcode, (w + 1in#, 0));";
else:
  special "labelfont cmtt8";
fi;

% Produce a |makelabel| command for each |z| point in |point_list| and
% each suffix in |suffixes|.
% 
def general_label (text point_list, suffixes) =
  forsuffixes point_suffix = ,suffixes:
    forsuffixes point = point_list:
      % Unfortunately, the way in which the |str| operator formats its
      % argument (which is an arbitrary suffix) cannot be changed, so
      % the proofsheets end up showing "0 0" for the variable |z[0][0]|.
      makelabel (str point.point_suffix, z.point.point_suffix);
    endfor
  endfor
enddef;

% Define our labels for the proofsheets.  The person running Metafont
% can also see the control points on each spline, by setting
% |proofing>2| at the beginning.  (The {\tt plain.mf} macros only
% distinguish between |proofing=0|, |proofing>0| and |proofing>1|, so we
% are not disturbing them.)
% 
def proof_labels (text t) =
  % We need to delimit the arguments here, so \MF\ knows where the
  % second |text| argument begins.  Our output uses the suffix |"s"| for
  % startpoints of segments, and the suffixes |"c1"| and |"c2"| for
  % control points.
  if proofing > 1: general_label (t) (s); fi;
  if proofing > 2: general_label (t) (c1,c2); fi;
enddef;


% We define our characters as filled outlines; page 206 of {\sl The
% Metafontbook} suggests disabling \MF's |autorounding| and
% |smoothing| features in that case.
% 
autorounding := 0;
smoothing := 0;

% Since we can easily make slanted fonts, we assign some angle to
% hangul_slant(usually 1/6). If we don't do it, we assume that we are
% making upright fonts.
if unknown hangul_slant: hangul_slant := 0;
else: currenttransform := identity slanted hangul_slant; fi
font_slant := hangul_slant;

% Metric stuff
if known default_metric:
  if unknown hfont_normal_space: font_normal_space := 3.23u#;
  else: font_normal_space := hfont_normal_space; fi;
  if unknown hfont_normal_stretch: font_normal_stretch := 3.24u#;
  else: font_normal_stretch := hfont_normal_stretch; fi;
  if unknown hfont_normal_shrink: font_normal_shrink := 3.23u#;
  else: font_normal_shrink := hfont_normal_shrink; fi;
  if unknown hfont_x_height: font_x_height := 6.58u#;
  else: font_x_height := hfont_x_height; fi;
  if unknown hfont_quad: font_quad := 9.72u#;
  else: font_quad := hfont_quad; fi;
fi

% hangul_x and hangul_y can make characters more thick. Since the output
% from bzrto tends to make light-weighted font and we are to make
% \bfseries fonts with this same output, we assign fine-tuned values
% to hangul_x and/or hangul_y.
% If we want to make outlined font, we may not fill_or_unfill the outline,
% but draw it. For the thickness of the line to be draw'ed we let
% MetaFont use the value assigned to hangul_outline.
% All these parameters must be set before this file, if any.
% <koaunghi.un@zdv>
if unknown hangul_outline:
  if known hangul_x:
    pen hangul_pen;
    if unknown hangul_y: hangul_y := hangul_x; fi;
    OLX# := hangul_x * pt#; OLY# := hangul_y * pt#;
    define_pixels (OLX, OLY);
    hangul_pen := pencircle xscaled OLX yscaled OLY;
  fi;
else:
  OL# := hangul_outline * pt#;
  define_pixels (OL);
  pen hangul_pen; hangul_pen := pencircle scaled OL;
fi;

% Sometimes we want to fill our paths, other times unfill them,
% depending on whether the winding number is positive or negative.  We
% could be absolutely safe here, and declare |temp_path| inside a group,
% at every invocation of |fill_or_unfill|; but this would waste time and
% space to no advantage, since we know exactly what kind of \MF\
% programs we output, and the variable |temp_path| is not used in them.
% 
% Incidentally, we need a variable in the first place only because it is more
% efficient to avoid evaluating long paths more than once.
% 
% To avoid huge \MF\ files, we filter the file with |bzrmf.awk|, which
% does followng: <koaunghi.un@zdv>
%   1. z[char_code][number][sequence] --> z[number][sequence]
%   2. fill_or_unfill (path) --> FoU(last_point, points_of_curves)
%   3. proof_labels(z[char_code][point][sequence],...)
%	--> proof_labels(z[point][sequence],...)
%   4. remove unnecessary blank spaces and lines.
% Now the macro FoU defined below does following:
%   1. set boolean operator |control[sequences_of_controls]| |true|
%   2. concatenate all points upto last point and assignes it
%      to |temp_path[subpath]|: if |control[i] = true|, its a curve,
%      if not, its a line.
%   3. For not-outlined font, |fill| this subpath.
%   4. Finally, the number for next part of subpath is increased
%      and |extra_endchar| does |fill| and |unfill| with the macro
%      |nonzerowinding|.
% Sometimes there is some bad paths, which does nothing, e.g.
%	|fill_or_unfill| z(start)--z(start);
% |bzrmf.awk| filters it and write NOP;
path temp_path[]; 
boolean control[], nop[];

def NOP = nop[PN] := true; PN := PN +1; enddef;

def nonzerowinding =
    cull currentpicture dropping (0,0);
    for i=0 upto PN-1: if not nop[i]: draw temp_path[i]; fi; endfor
enddef;
extra_endchar := extra_endchar & "nonzerowinding;";
extra_beginchar := extra_beginchar & "PN := 0;";
%
vardef FoU(expr last)(text p) =
  for i = 0 upto last: control[i] := false; endfor;
  forsuffixes s = p: control[s] := true; endfor;
  temp_path[PN] :=
    z[PN]0s
    for i = 0 upto last:
      if control[i]:
        ..controls z[PN][i]c1 and z[PN][i]c2..
        if i = last: cycle else: z[PN][i] fi
      else:
        if i = last: --cycle else: --z[PN][i] fi
      fi
    endfor;
  nop[PN] := false;
  if known hangul_pen: pickup hangul_pen; fi;
  if unknown hangul_outline: fill (temp_path[PN]); fi;
  PN := PN + 1;
enddef;

% Since we can assume the font fills all cycles counterclockwise
% (because PostScript requires this), we want to disable the
% |turningnumber| checking which generates the `Strange path' errors.
% See p.112 and p.119 of the Metafontbook.
% 
% (By the way, setting |turningcheck := 0| makes Metafont always use the
% filling rule for positive turning number, i.e., always |fill| and
% never |unfill|.  When would this be useful?)
% 
%turningcheck := 1;
%
% In some cases, probably where |mf| encounters complicated pathes (e.g.
% Hanja-Myoungjo), setting |turnichngcheck:=1| tries to reverse the path
% to avoid the `Strange path' errors and does |unfill| instead |fill|.
% |ps2mfbas.mf| does firstly |fill| all pathes and |dropping (0,0)|
% the final |currentpicture| before |shipout|. The macro FoU uses
% this methode <koaunghi.un@zdv>
turningcheck := 0;

% When we don't know the dimensions of the character we're defining
% before we define it, we have to use these to begin it:
def begin_no_dimen_char (expr c) =
  begingroup
  transform save_currenttransform;
  save_currenttransform := currenttransform;
  charcode:=if known c: byte c else: 0 fi;
  charic:=0; clearxy; clearit; clearpen; scantokens extra_beginchar;
enddef;

def end_no_dimen_char =
  currenttransform := save_currenttransform;
  endchar;
enddef;

% When use the above to start a character, must call this before `endchar'.
% 
def set_char_dimens (expr w_sharp,h_sharp,d_sharp) =
 charwd:=w_sharp;      charht:=h_sharp;       chardp:=d_sharp;
 w:=hround(charwd*hppp); h:=vround(charht*hppp); d:=vround(chardp*hppp);
enddef;

% Move by shifting the current transform matrix.
% 
def move (expr h_amount, v_amount) =
  currenttransform := currenttransform shifted (h_amount, v_amount);
enddef;

def hmove (expr amount) = move (amount, 0); enddef;
def vmove (expr amount) = move (0, amount); enddef;
