{$A-,B-,D-,E-,F-,I+,L-,N-,O-,R-,S-,V-}
{Compile with Turbo-Pascal 5.0}
Program JIS2MF(Input,Output);
{
  This program generates METAFONT code from a Bitmaps file JIS24

  Author: Francois Jalbert
              '
  Date: November 1990

  Version: 1.0

  Date: April 1991

  Version: 2.00

  Modifications: - Added four kanjis.
                 - Fixed incorrect VGA resolution.
                 - Command line parameter now supported.
                 - Added automatic mode.
                 - Added batch mode.
                 - Updated and improved run-time messages.
                 - Long triangles added by Mr. Masatoshi Watanabe. Fantastic!
                 - Fixed and proportional parameters added.
                 - Standard and dictionary parameters added.
                 - JIS24 now accessed through low-level I/O channel for speed.

  Error Levels: 0 - Normal termination.
                1 - Error.
                2 - All fonts generated (batch).
}
Const
  {Number of Bitmaps in JIS24}
  BitmapMax=7806;
  {Size of each square Bitmap}
  SizeMax=24;
  SizeMax1=25;
  {DOS Record Size}
  RecSize=72; {SizeMax*SizeMax/8}
  {Parameter flag}
  Flag1='/'; {DOS style}
  Flag2='-'; {UNIX style}
  {Parameter keywords}
  FixedX1:String[10]='FIXEDWIDTH';
  FixedX2:String[6]='FIXEDX';
  FixedX3:String[19]='NOPROPORTIONALWIDTH';
  FixedX4:String[15]='NOPROPORTIONALX';
  NoFixedX1:String[12]='NOFIXEDWIDTH';
  NoFixedX2:String[8]='NOFIXEDX';
  NoFixedX3:String[17]='PROPORTIONALWIDTH';
  NoFixedX4:String[13]='PROPORTIONALX';
  FixedY1:String[11]='FIXEDHEIGHT';
  FixedY2:String[6]='FIXEDY';
  FixedY3:String[20]='NOPROPORTIONALHEIGHT';
  FixedY4:String[15]='NOPROPORTIONALY';
  NoFixedY1:String[13]='NOFIXEDHEIGHT';
  NoFixedY2:String[8]='NOFIXEDY';
  NoFixedY3:String[18]='PROPORTIONALHEIGHT';
  NoFixedY4:String[13]='PROPORTIONALY';
  Standard1:String[8]='STANDARD';
  NoStandard1:String[10]='DICTIONARY';
  Batch1:String[5]='BATCH';

Type
  InFileType=File; {Low-level I/O channel}
  OutFileType=Text;
  BitmapRange=1..BitmapMax;
  Bitmap0Range=0..BitmapMax;
  SizeRange=1..SizeMax;
  Size0Range=0..SizeMax1;
  {Buffer for the Bitmap Data}
  ColumnType=Record Data1,Data2,Data3:Byte End;
  BufferType=Array [SizeRange] Of ColumnType;
  {The Bitmap array is defined larger to simplify the forthcoming code}
  BitmapType=Array [Size0Range,Size0Range] Of Boolean;
  BitmapsType=Record
                Bitmap:BitmapType;
                XMin,XMax,YMin,YMax:Size0Range
              End;
  {Run time parameters}
  RunTimeType=Record
                FileName:String;
                {Batch mode}
                Batch:Boolean;
                {Automatic mode for JemTeX fonts only}
                Automatic:Boolean;
                {Fixed or proportional fonts}
                FixedX,FixedY:Boolean;
                {Standard or dictionary fonts}
                Standard:Boolean
              End;

Var
  {JIS24 and METAFONT file names}
  InFile:InFileType;
  OutFile:OutFileType;
  {Current METAFONT character number}
  Number:Integer;
  {Run time parameters}
  RunTime:RunTimeType;

{-------------------------------- GetParameters ------------------------------}

Procedure SimpleQuery(Title,ChoiceA,ChoiceB:String; Var Answer:Boolean);
Var
  JChar:Char;
  Valid:Boolean;
Begin
Repeat
  Valid:=True;
  Writeln(Title+':');
  Writeln('   a)  '+ChoiceA);
  Writeln('   b)  '+ChoiceB);
  Write('Your choice? ');
  Readln(JChar);
  JChar:=UpCase(JChar);
  If JChar='A' Then Answer:=True
  Else
    If JChar='B' Then Answer:=False
    Else
      Begin Valid:=False; Write(Chr(7)) End
Until Valid;
Writeln
End;

Procedure GetMode(Var RunTime:RunTimeType);
{Determines if the desired font is a JemTeX font}
Begin
With RunTime Do
  Begin
  Automatic:=False;
  If UpCase(FileName[1])='K' Then
  If UpCase(FileName[2])='A' Then
  If UpCase(FileName[3])='N' Then
  If UpCase(FileName[4])='J' Then
  If UpCase(FileName[5])='I' Then
  If ('A'<=UpCase(FileName[6])) And (UpCase(FileName[6])<='H') Then
  If ('A'<=UpCase(FileName[7])) And (UpCase(FileName[7])<='H') Then
  If Length(FileName)=7 Then
  If UpCase(FileName[6])<='G' Then Automatic:=True
  Else
  If UpCase(FileName[7])<='E' Then Automatic:=True
  End
End;

Procedure EchoParameters(Var RunTime:RunTimeType);
{Echoes the current parameters}
Begin
With RunTime Do
  Begin
  Write('Font='+FileName);
  If FixedX Then Write('  Fixed Width')
  Else Write('  Prop. Width');
  If FixedY Then Write('  Fixed Height')
  Else Write('  Prop. Height');
  If Standard Then Write('  Standard')
  Else Write('  Dictionary');
  If Automatic Then Write('  Automatic')
  Else Write('  Manual');
  If Batch Then Write('  Batch');
  Writeln('.')
  End
End;

Procedure Manual(Var RunTime:RunTimeType);
{Get parameters from user}
Begin
With RunTime Do
  Begin
  Write('METAFONT file name? ');
  Readln(FileName);
  Writeln;
  SimpleQuery('Fixed or proportional font width','Fixed','Proportional',FixedX);
  SimpleQuery('Fixed or proportional font height','Fixed','Proportional',FixedY);
  SimpleQuery('Standard or dictionary font','Standard','Dictionary',Standard);
  {Batch mode intrinsically isn't manual}
  Batch:=False
  End
End;

Procedure FindBefore(Var FileName:String);
{No check for before kanjiaa}
Begin
If FileName[7]='a' Then
  Begin
  FileName[7]:='h';
  FileName[6]:=Pred(FileName[6])
  End
Else
  FileName[7]:=Pred(FileName[7])
End;

Procedure FindAfter(Var FileName:String);
{No check for above kanjihe}
Begin
If FileName[7]='h' Then
  Begin
  FileName[7]:='a';
  FileName[6]:=Succ(FileName[6])
  End
Else
  FileName[7]:=Succ(FileName[7])
End;

Procedure ScanMF(Var FileName:String);
{Scans backwards for the last JemTeX font generated}
{Looks first for a .TFM and then for an .MF}
{If no more fonts to generate, stops with error level 2}
Var 
  TestFile:Text;
  Found:Boolean;
Begin
FileName:='kanjihf';
Repeat
  FindBefore(FileName);
  Assign(TestFile,FileName+'.tfm');
  {$I-}Reset(TestFile);{$I+}
  {IOResult must be immediately used once only}
  Found:=(IOResult=0);
  If Not Found Then 
    Begin
    Assign(TestFile,FileName+'.mf');
    {$I-}Reset(TestFile);{$I+}
    {IOResult must be immediately used once only}
    Found:=(IOResult=0)
    End;
Until Found Or (FileName='kanjiaa');
If Found Then
  Begin
  Close(TestFile);
  If FileName='kanjihe' Then
    Begin
    Writeln(Chr(7)+'All JemTeX fonts generated!');
    Halt(2)
    End
  Else FindAfter(FileName)
  End
End;

Procedure Automate(Var RunTime:RunTimeType);
{Get parameters from command line}
{Finds the next font to be generated if in batch mode}
Var
  ParamIndex,Index:Integer;
  Param:String;
Begin
With RunTime Do
  Begin
  {Defaults}
  FileName:='kanjiaa';
  FixedX:=False;
  FixedY:=False;
  Standard:=True;
  Batch:=False;
  {Scan command line parameters}
  For ParamIndex:=1 To ParamCount Do
    Begin
    Param:=ParamStr(ParamIndex);
    If (Param[1]=Flag1) Or (Param[1]=Flag2) Then
      {Not a font name}
      Begin
      {Delete 1 char at the 1st position}
      Delete(Param,1,1);
      {Convert to upper case}
      For Index:=1 To Length(Param) Do 
        Param[Index]:=UpCase(Param[Index]);
      {Scan known keywords}
      If (Param=FixedX1) Or (Param=FixedX2) Or (Param=FixedX3) Or 
         (Param=FixedX4) Then FixedX:=True
      Else
      If (Param=NoFixedX1) Or (Param=NoFixedX2) Or (Param=NoFixedX3) Or 
         (Param=NoFixedX4) Then FixedX:=False
      Else
      If (Param=FixedY1) Or (Param=FixedY2) Or (Param=FixedY3) Or 
         (Param=FixedY4) Then FixedY:=True
      Else
      If (Param=NoFixedY1) Or (Param=NoFixedY2) Or (Param=NoFixedY3) Or 
         (Param=NoFixedY4) Then FixedY:=False
      Else
      If Param=Standard1 Then Standard:=True
      Else
      If Param=NoStandard1 Then Standard:=False
      Else
      If Param=Batch1 Then Batch:=True
      Else
        {Unknown keyword}
        Begin
        Writeln(Chr(7)+'Invalid command line parameter: '+Param+'...');
        Halt(1)
        End
      End
    Else
      {Must be a font name}
      FileName:=Param
    End;
  If Batch Then ScanMF(FileName)
  End
End;

Procedure GetParameters(Var RunTime:RunTimeType);
{Get parameters from user or command line}
Begin
If ParamCount=0 Then Manual(RunTime)
Else Automate(RunTime);
GetMode(RunTime);
EchoParameters(RunTime);
Writeln
End;

{----------------------------------- Output ----------------------------------}

Procedure BeginOut(Var OutFile:OutFileType; Var RunTime:RunTimeType);
{Writes initial METAFONT header}
{Co-author is Mr. Masatoshi Watanabe}
Begin
Writeln(OutFile,'%JIS2MF Version 2.00 of 14 April 1991.');
Writeln(OutFile);
Writeln(OutFile,'% Font='+RunTime.FileName);
If RunTime.FixedX Then Writeln(OutFile,'% Fixed Width')
Else Writeln(OutFile,'% Proportional Width');
If RunTime.FixedY Then Writeln(OutFile,'% Fixed Height')
Else Writeln(OutFile,'% Proportional Height');
If RunTime.Standard Then Writeln(OutFile,'% Standard Positioning')
Else Writeln(OutFile,'% Dictionary Positioning');
Writeln(OutFile);
Writeln(OutFile,'tracingstats:=1;');
Writeln(OutFile,'screen_cols:=640; %VGA');
Writeln(OutFile,'screen_rows:=480; %VGA');
Writeln(OutFile,'font_size 10pt#;');
If RunTime.Standard Then
  Begin
  Writeln(OutFile,'u#:=12.7/36pt#;');
  Writeln(OutFile,'body_height#:=23.25u#;');
  Writeln(OutFile,'desc_depth#:=4.75u#;')
  End
Else
  Begin
  Writeln(OutFile,'u#:=13/36pt#;');
  Writeln(OutFile,'body_height#:=21u#;');
  Writeln(OutFile,'desc_depth#:=7u#;')
  End;
Writeln(OutFile);
Writeln(OutFile,'letter_fit#:=0pt#;');
Writeln(OutFile,'asc_height#:=0pt#;');
Writeln(OutFile,'cap_height#:=0pt#;');
Writeln(OutFile,'fig_height#:=0pt#;');
Writeln(OutFile,'x_height#:=0pt#;');
Writeln(OutFile,'math_axis#:=0pt#;');
Writeln(OutFile,'bar_height#:=0pt#;');
Writeln(OutFile,'comma_depth#:=0pt#;');
Writeln(OutFile,'crisp#:=0pt#;');
Writeln(OutFile,'tiny#:=0pt#;');
Writeln(OutFile,'fine#:=0pt#;');
Writeln(OutFile,'thin_join#:=0pt#;');
Writeln(OutFile,'hair#:=1pt#;');
Writeln(OutFile,'stem#:=1pt#;');
Writeln(OutFile,'curve#:=1pt#;');
Writeln(OutFile,'flare#:=1pt#;');
Writeln(OutFile,'dot_size#:=0pt#;');
Writeln(OutFile,'cap_hair#:=1pt#;');
Writeln(OutFile,'cap_stem#:=1pt#;');
Writeln(OutFile,'cap_curve#:=1pt#;');
Writeln(OutFile,'rule_thickness#:=0pt#;');
Writeln(OutFile,'vair#:=0pt#;');
Writeln(OutFile,'notch_cut#:=0pt#;');
Writeln(OutFile,'bar#:=1pt#;');
Writeln(OutFile,'slab#:=1pt#;');
Writeln(OutFile,'cap_bar#:=1pt#;');
Writeln(OutFile,'cap_band#:=1pt#;');
Writeln(OutFile,'cap_notch_cut#:=0pt#;');
Writeln(OutFile,'serif_drop#:=0pt#;');
Writeln(OutFile,'stem_corr#:=0pt#;');
Writeln(OutFile,'vair_corr#:=0pt#;');
Writeln(OutFile,'o#:=0pt#;');
Writeln(OutFile,'apex_o#:=0pt#;');
Writeln(OutFile,'hefty:=true;');
Writeln(OutFile,'serifs:=true;');
Writeln(OutFile,'monospace:=false;');
Writeln(OutFile,'math_fitting:=false;');
Writeln(OutFile);
Writeln(OutFile,'mode_setup;');
Writeln(OutFile,'font_setup;');
Writeln(OutFile);
Writeln(OutFile,'pair z;');
Writeln(OutFile);
Writeln(OutFile,'def s(expr col,row)= %square');
Writeln(OutFile,' z:=((col*u),(row*u));');
Writeln(OutFile,' fill unitsquare scaled u shifted z;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def sul(expr col,row)= %upper left square');
Writeln(OutFile,' z:=((col*u),(row*u)+.5u);');
Writeln(OutFile,' fill unitsquare scaled .5u shifted z;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def sur(expr col,row)= %upper right square');
Writeln(OutFile,' z:=((col*u)+.5u,(row*u)+.5u);');
Writeln(OutFile,' fill unitsquare scaled .5u shifted z;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def sbr(expr col,row)= %bottom right square');
Writeln(OutFile,' z:=((col*u)+.5u,(row*u));');
Writeln(OutFile,' fill unitsquare scaled .5u shifted z;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def sbl(expr col,row)= %bottom left square');
Writeln(OutFile,' z:=((col*u),(row*u));');
Writeln(OutFile,' fill unitsquare scaled .5u shifted z;');
Writeln(OutFile,'enddef;');
Writeln(OutFile);
Writeln(OutFile,'def c(expr col,row)= %circle');
Writeln(OutFile,' z:=((col*u)+.5u,(row*u)+.5u);');
Writeln(OutFile,' fill fullcircle scaled u shifted z;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def cul(expr col,row)= %upper left circle');
Writeln(OutFile,' z:=((col*u)+.5u,(row*u)+.5u);');
Writeln(OutFile,' fill z--quartercircle rotated 90 scaled u shifted z--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def cur(expr col,row)= %upper right circle');
Writeln(OutFile,' z:=((col*u)+.5u,(row*u)+.5u);');
Writeln(OutFile,' fill z--quartercircle scaled u shifted z--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def cbr(expr col,row)= %bottom right circle');
Writeln(OutFile,' z:=((col*u)+.5u,(row*u)+.5u);');
Writeln(OutFile,' fill z--quartercircle rotated 270 scaled u shifted z--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def cbl(expr col,row)= %bottom left circle');
Writeln(OutFile,' z:=((col*u)+.5u,(row*u)+.5u);');
Writeln(OutFile,' fill z--quartercircle rotated 180 scaled u shifted z--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile);
Writeln(OutFile,'def tul(expr col,row)= %upper left triangle');
Writeln(OutFile,' z:=((col*u)+.5u,(row*u)+.5u);');
Writeln(OutFile,' fill z--z+(0,.5u)--z-(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def tur(expr col,row)= %upper right triangle');
Writeln(OutFile,' z:=((col*u)+.5u,(row*u)+.5u);');
Writeln(OutFile,' fill z--z+(0,.5u)--z+(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def tbr(expr col,row)= %bottom right triangle');
Writeln(OutFile,' z:=((col*u)+.5u,(row*u)+.5u);');
Writeln(OutFile,' fill z--z-(0,.5u)--z+(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def tbl(expr col,row)= %bottom left triangle');
Writeln(OutFile,' z:=((col*u)+.5u,(row*u)+.5u);');
Writeln(OutFile,' fill z--z-(0,.5u)--z-(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile);
Writeln(OutFile,'def rul(expr col,row)= %upper left reverse triangle');
Writeln(OutFile,' z:=((col*u),(row*u)+u);');
Writeln(OutFile,' fill z--z-(0,.5u)--z+(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def rur(expr col,row)= %upper right reverse triangle');
Writeln(OutFile,' z:=((col*u)+u,(row*u)+u);');
Writeln(OutFile,' fill z--z-(0,.5u)--z-(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def rbr(expr col,row)= %bottom right reverse triangle');
Writeln(OutFile,' z:=((col*u)+u,(row*u));');
Writeln(OutFile,' fill z--z+(0,.5u)--z-(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def rbl(expr col,row)= %bottom left reverse triangle');
Writeln(OutFile,' z:=((col*u),(row*u));');
Writeln(OutFile,' fill z--z+(0,.5u)--z+(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile);
Writeln(OutFile,'def tuul(expr col,row)= %upper left long triangle');
Writeln(OutFile,' z:=((col*u)+u,(row*u)+.5u);');
Writeln(OutFile,' fill z--z+(0,.5u)--z-(u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def tull(expr col,row)= %upper left long triangle');
Writeln(OutFile,' z:=((col*u)+.5u,(row*u));');
Writeln(OutFile,' fill z--z+(0,u)--z-(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def tuur(expr col,row)= %upper right long triangle');
Writeln(OutFile,' z:=((col*u),(row*u)+.5u);');
Writeln(OutFile,' fill z--z+(0,.5u)--z+(u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def turr(expr col,row)= %upper right long triangle');
Writeln(OutFile,' z:=((col*u)+.5u,(row*u));');
Writeln(OutFile,' fill z--z+(0,u)--z+(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def tbbr(expr col,row)= %bottom right long triangle');
Writeln(OutFile,' z:=((col*u),(row*u)+.5u);');
Writeln(OutFile,' fill z--z-(0,.5u)--z+(u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def tbrr(expr col,row)= %bottom right long triangle');
Writeln(OutFile,' z:=((col*u)+.5u,(row*u)+u);');
Writeln(OutFile,' fill z--z-(0,u)--z+(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def tbbl(expr col,row)= %bottom left long triangle');
Writeln(OutFile,' z:=((col*u)+u,(row*u)+.5u);');
Writeln(OutFile,' fill z--z-(0,.5u)--z-(u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def tbll(expr col,row)= %bottom left long triangle');
Writeln(OutFile,' z:=((col*u)+.5u,(row*u)+u);');
Writeln(OutFile,' fill z--z-(0,u)--z-(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile);
Writeln(OutFile,'def ruul(expr col,row)= %upper left reverse long triangle');
Writeln(OutFile,' z:=((col*u),(row*u)+u);');
Writeln(OutFile,' fill z--z-(0,u)--z+(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def rull(expr col,row)= %upper left reverse long triangle');
Writeln(OutFile,' z:=((col*u),(row*u)+u);');
Writeln(OutFile,' fill z--z-(0,.5u)--z+(u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def ruur(expr col,row)= %upper right reverse long triangle');
Writeln(OutFile,' z:=((col*u)+u,(row*u)+u);');
Writeln(OutFile,' fill z--z-(0,u)--z-(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def rurr(expr col,row)= %upper right reverse long triangle');
Writeln(OutFile,' z:=((col*u)+u,(row*u)+u);');
Writeln(OutFile,' fill z--z-(0,.5u)--z-(u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def rbbr(expr col,row)= %bottom right reverse long triangle');
Writeln(OutFile,' z:=((col*u)+u,(row*u));');
Writeln(OutFile,' fill z--z+(0,u)--z-(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def rbrr(expr col,row)= %bottom right reverse long triangle');
Writeln(OutFile,' z:=((col*u)+u,(row*u));');
Writeln(OutFile,' fill z--z+(0,.5u)--z-(u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def rbbl(expr col,row)= %bottom left reverse long triangle');
Writeln(OutFile,' z:=((col*u),(row*u));');
Writeln(OutFile,' fill z--z+(0,u)--z+(.5u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile,'def rbll(expr col,row)= %bottom left reverse long triangle');
Writeln(OutFile,' z:=((col*u),(row*u));');
Writeln(OutFile,' fill z--z+(0,.5u)--z+(u,0)--cycle;');
Writeln(OutFile,'enddef;');
Writeln(OutFile)
End;

Procedure ActiveBitmap(Var OutFile:OutFileType; Var Bitmap:BitmapType; 
                       X,Y:SizeRange; XX:Integer; YY:Real);
{Writes METAFONT code for an active cell}
{Co-author is Mr. Masatoshi Watanabe}
Var
  SquareUR,SquareUL,SquareBR,SquareBL:Boolean;
  CircleUR,CircleUL,CircleBR,CircleBL:Boolean;
  LTryUUR,LTryURR,LTryUUL,LTryULL:Boolean;
  LTryBBR,LTryBRR,LTryBBL,LTryBLL:Boolean;
Begin
SquareUL:=(Bitmap[X-1,Y] Or Bitmap[X-1,Y+1] Or Bitmap[X,Y+1]);
SquareUR:=(Bitmap[X+1,Y] Or Bitmap[X+1,Y+1] Or Bitmap[X,Y+1]);
SquareBL:=(Bitmap[X-1,Y] Or Bitmap[X-1,Y-1] Or Bitmap[X,Y-1]);
SquareBR:=(Bitmap[X+1,Y] Or Bitmap[X+1,Y-1] Or Bitmap[X,Y-1]);
CircleUL:=(Not Bitmap[X-1,Y-1] And Not Bitmap[X-1,Y] And Not Bitmap[X-1,Y+1] And
           Not Bitmap[X,Y+1] And Not Bitmap[X+1,Y+1]);
CircleUR:=(Not Bitmap[X+1,Y-1] And Not Bitmap[X+1,Y] And Not Bitmap[X+1,Y+1] And
           Not Bitmap[X,Y+1] And Not Bitmap[X-1,Y+1]);
CircleBL:=(Not Bitmap[X-1,Y+1] And Not Bitmap[X-1,Y] And Not Bitmap[X-1,Y-1] And
           Not Bitmap[X,Y-1] And Not Bitmap[X+1,Y-1]);
CircleBR:=(Not Bitmap[X+1,Y+1] And Not Bitmap[X+1,Y] And Not Bitmap[X+1,Y-1] And
           Not Bitmap[X,Y-1] And Not Bitmap[X-1,Y-1]);
LTryUUL:=(Bitmap[X-1,Y-1] And Not Bitmap[X-1,Y] And Not Bitmap[X-1,Y+1] And
          Not Bitmap[X,Y+1] And Not Bitmap[X+1,Y+1] And Bitmap[X+1,Y]);
LTryUUR:=(Bitmap[X+1,Y-1] And Not Bitmap[X+1,Y] And Not Bitmap[X+1,Y+1] And
          Not Bitmap[X,Y+1] And Not Bitmap[X-1,Y+1] And Bitmap[X-1,Y]);
LTryBBL:=(Bitmap[X-1,Y+1] And Not Bitmap[X-1,Y] And Not Bitmap[X-1,Y-1] And
          Not Bitmap[X,Y-1] And Not Bitmap[X+1,Y-1] And Bitmap[X+1,Y]);
LTryBBR:=(Bitmap[X+1,Y+1] And Not Bitmap[X+1,Y] And Not Bitmap[X+1,Y-1] And
          Not Bitmap[X,Y-1] And Not Bitmap[X-1,Y-1] And Bitmap[X-1,Y]);
LTryULL:=(Not Bitmap[X-1,Y-1] And Not Bitmap[X-1,Y] And Not Bitmap[X-1,Y+1] And
          Not Bitmap[X,Y+1] And Bitmap[X+1,Y+1] And Bitmap[X,Y-1]);
LTryURR:=(Not Bitmap[X+1,Y-1] And Not Bitmap[X+1,Y] And Not Bitmap[X+1,Y+1] And
          Not Bitmap[X,Y+1] And Bitmap[X-1,Y+1] And Bitmap[X,Y-1]);
LTryBLL:=(Not Bitmap[X-1,Y+1] And Not Bitmap[X-1,Y] And Not Bitmap[X-1,Y-1] And
          Not Bitmap[X,Y-1] And Bitmap[X+1,Y-1] And Bitmap[X,Y+1]);
LTryBRR:=(Not Bitmap[X+1,Y+1] And Not Bitmap[X+1,Y] And Not Bitmap[X+1,Y-1] And
          Not Bitmap[X,Y-1] And Bitmap[X-1,Y-1] And Bitmap[X,Y+1]);
If LTryUUL Then Write(OutFile,'tuul(',XX,',',YY:4:2,');');
If LTryULL Then Write(OutFile,'tull(',XX,',',YY:4:2,');');
If LTryUUR Then Write(OutFile,'tuur(',XX,',',YY:4:2,');');
If LTryURR Then Write(OutFile,'turr(',XX,',',YY:4:2,');');
If LTryBBL Then Write(OutFile,'tbbl(',XX,',',YY:4:2,');');
If LTryBLL Then Write(OutFile,'tbll(',XX,',',YY:4:2,');');
If LTryBBR Then Write(OutFile,'tbbr(',XX,',',YY:4:2,');');
If LTryBRR Then Write(OutFile,'tbrr(',XX,',',YY:4:2,');');
If SquareUL And SquareUR And SquareBL And SquareBR Then
  Write(OutFile,'s(',XX,',',YY:4:2,');')
Else
  If CircleUL And CircleUR And CircleBL And CircleBR Then
    Write(OutFile,'c(',XX,',',YY:4:2,');')
  Else
    Begin
    If Not LTryUUL And Not LTryULL And Not LTryUUR And Not LTryBLL Then
      If SquareUL Then Write(OutFile,'sul(',XX,',',YY:4:2,');')
      Else
        If CircleUL Then Write(OutFile,'cul(',XX,',',YY:4:2,');')
        Else Write(OutFile,'tul(',XX,',',YY:4:2,');');
    If Not LTryUUL And Not LTryURR And Not LTryUUR And Not LTryBRR Then
      If SquareUR Then Write(OutFile,'sur(',XX,',',YY:4:2,');')
      Else
        If CircleUR Then Write(OutFile,'cur(',XX,',',YY:4:2,');')
        Else Write(OutFile,'tur(',XX,',',YY:4:2,');');
    If Not LTryBBL And Not LTryULL And Not LTryBBR And Not LTryBLL Then
      If SquareBL Then Write(OutFile,'sbl(',XX,',',YY:4:2,');')
      Else
        If CircleBL Then Write(OutFile,'cbl(',XX,',',YY:4:2,');')
        Else Write(OutFile,'tbl(',XX,',',YY:4:2,');');
    If Not LTryBBL And Not LTryURR And Not LTryBBR And Not LTryBRR Then
      If SquareBR Then Write(OutFile,'sbr(',XX,',',YY:4:2,');')
      Else
        If CircleBR Then Write(OutFile,'cbr(',XX,',',YY:4:2,');')
        Else Write(OutFile,'tbr(',XX,',',YY:4:2,');')
    End
End;

Procedure InactiveBitmap(Var OutFile:OutFileType; Var Bitmap:BitmapType;
                         X,Y:SizeRange; XX:Integer; YY:Real; Var Active:Boolean);
{Writes METAFONT code for an inactive cell}
{Co-author is Mr. Masatoshi Watanabe}
Begin
If Bitmap[X-1,Y] And Bitmap[X,Y+1] Then
  If Bitmap[X-1,Y-1] And Not Bitmap[X+1,Y+1] Then
    Begin Active:=True; Write(OutFile,'ruul(',XX,',',YY:4:2,');') End
  Else
    If Bitmap[X+1,Y+1] And Not Bitmap[X-1,Y-1] Then
      Begin Active:=True; Write(OutFile,'rull(',XX,',',YY:4:2,');') End
    Else
      Begin Active:=True; Write(OutFile,'rul(',XX,',',YY:4:2,');') End;
If Bitmap[X+1,Y] And Bitmap[X,Y+1] Then
  If Bitmap[X+1,Y-1] And Not Bitmap[X-1,Y+1] Then
    Begin Active:=True; Write(OutFile,'ruur(',XX,',',YY:4:2,');') End
  Else
    If Bitmap[X-1,Y+1] And Not Bitmap[X+1,Y-1] Then
      Begin Active:=True; Write(OutFile,'rurr(',XX,',',YY:4:2,');') End
    Else
      Begin Active:=True; Write(OutFile,'rur(',XX,',',YY:4:2,');') End;
If Bitmap[X-1,Y] And Bitmap[X,Y-1] Then
  If Bitmap[X-1,Y+1] And Not Bitmap[X+1,Y-1] Then
    Begin Active:=True; Write(OutFile,'rbbl(',XX,',',YY:4:2,');') End
  Else
    If Bitmap[X+1,Y-1] And Not Bitmap[X-1,Y+1] Then
      Begin Active:=True; Write(OutFile,'rbll(',XX,',',YY:4:2,');') End
    Else
      Begin Active:=True; Write(OutFile,'rbl(',XX,',',YY:4:2,');') End;
If Bitmap[X+1,Y] And Bitmap[X,Y-1] Then
  If Bitmap[X+1,Y+1] And Not Bitmap[X-1,Y-1] Then
    Begin Active:=True; Write(OutFile,'rbbr(',XX,',',YY:4:2,');') End
  Else
    If Bitmap[X-1,Y-1] And Not Bitmap[X+1,Y+1] Then
      Begin Active:=True; Write(OutFile,'rbrr(',XX,',',YY:4:2,');') End
    Else
      Begin Active:=True; Write(OutFile,'rbr(',XX,',',YY:4:2,');') End
End;

Procedure MiddleOut(Var OutFile:OutFileType; Var Bitmaps:BitmapsType; 
                    Number:Integer; Standard:Boolean);
{Writes METAFONT code for a given Bitmap}
Var 
  X,Y:SizeRange;
  Active:Boolean;
Begin
With Bitmaps Do
  Begin
  Write(OutFile,'beginchar(',Number,',',XMax-XMin+1,'u#,');
  If Standard Then
    Begin
    If YMax>0.75 Then Write(OutFile,(YMax-0.75):4:2,'u#,')
    Else Write(OutFile,'0,');
    If 5.75>YMin Then Writeln(OutFile,(5.75-YMin):4:2,'u#);')
    Else Writeln(OutFile,'0);')
    End
  Else
    Begin
    If YMax>3 Then Write(OutFile,YMax-3,'u#,')
    Else Write(OutFile,'0,');
    If 8>YMin Then Writeln(OutFile,8-YMin,'u#);')
    Else Writeln(OutFile,'0);')
    End;
  Writeln(OutFile,'normal_adjust_fit(2u#,2u#);');
  For X:=XMin To XMax Do
    For Y:=1 To SizeMax Do
      Begin
      Active:=Bitmap[X,Y];
      If Active Then
        {Current pixel is on}
        If Standard Then ActiveBitmap(OutFile,Bitmap,X,Y,X-XMin,Y-3.75)
        Else ActiveBitmap(OutFile,Bitmap,X,Y,X-XMin,Y-6)
      Else
        {Current pixel is off}
        If Standard Then InactiveBitmap(OutFile,Bitmap,X,Y,X-XMin,Y-3.75,Active)
        Else InactiveBitmap(OutFile,Bitmap,X,Y,X-XMin,Y-6,Active);
      {Avoid METAFONT buffer overflow}
      If Active Then Writeln(OutFile)
      End;
  Writeln(OutFile,'endchar;');
  Writeln(OutFile)
  End
End; 

Procedure EndOut(Var OutFile:OutFileType; Var RunTime:RunTimeType);
{Writes final METAFONT header}
Begin
Writeln(OutFile,'font_identifier "'+RunTime.FileName+'";');
If RunTime.Standard Then 
  Writeln(OutFile,'font_coding_scheme "JemTeX Standard";')
Else Writeln(OutFile,'font_coding_scheme "JemTeX Dictionary";');
Writeln(OutFile,'font_slant slant;');
Writeln(OutFile,'font_normal_space 8u#;');
Writeln(OutFile,'font_normal_stretch 4u#;');
Writeln(OutFile,'font_normal_shrink 3u#;');
Writeln(OutFile,'font_x_height 24u#; %ex');
Writeln(OutFile,'font_quad 24u#; %em');
Writeln(OutFile,'font_extra_space 0u#;');
Writeln(OutFile);
{Must end with CR/LF because of a bug(?) in emTeX METAFONT}
Writeln(OutFile,'bye')
End;

{---------------------------------- Generate ---------------------------------}

Procedure FindWantedBitmap(Automatic:Boolean; Var First:Boolean;
                           Var WantedBitmap:Bitmap0Range; Var Number:Integer);
{Finds the number of the next desired Bitmap either automatically or manually}
{The characters 0 and 1 in the first font kanjiaa are both set to Bitmap 1}
Var Valid:Boolean;
Begin
If Automatic Then
  {Find automatically}
  If First Then
    {Early in font kanjiaa}
    If WantedBitmap=-1 Then WantedBitmap:=1
    Else
      Begin
      WantedBitmap:=1;
      First:=False
      End
  Else
    If (Number=128) Or (WantedBitmap=BitmapMax) Then WantedBitmap:=0
    Else WantedBitmap:=WantedBitmap+1
Else
  {Find manually}
  Repeat
    Write('Bitmap number? ');
    Readln(WantedBitmap);
    Writeln;
    Valid:=( (0<=WantedBitmap) And (WantedBitmap<=BitmapMax) );
    If Not Valid Then Writeln(Chr(7)+'Bitmap ',WantedBitmap,' out of range...')
  Until Valid;
Writeln('Bitmap number ',WantedBitmap,'.')
End;

Procedure ScanBitmap(Var InFile:InFileType; Var Bitmap:BitmapType;
                     Var Empty:Boolean);
{Reads the Bitmap in a logical grid}
{(0,0) is the lower left corner of the Bitmap}
Label 1;
Var
  Y:SizeRange;
  Buffer:BufferType;
Begin
{Read the Bitmap}
BlockRead(InFile,Buffer,1);
{Find if the Bitmap is empty}
Empty:=True;
For Y:=1 To SizeMax Do
  With Buffer[Y] Do
    If (Data1<>$00) Or (Data2<>$00) Or (Data3<>$00) Then
      Begin
      Empty:=False;
      Goto 1
      End;
{Update logical grid}
1:If Not Empty Then
  For Y:=1 To SizeMax Do 
    With Buffer[SizeMax1-Y] Do
      Begin
      Bitmap[ 1,Y]:=((Data1 And $80)<>0);
      Bitmap[ 2,Y]:=((Data1 And $40)<>0);
      Bitmap[ 3,Y]:=((Data1 And $20)<>0);
      Bitmap[ 4,Y]:=((Data1 And $10)<>0);
      Bitmap[ 5,Y]:=((Data1 And $08)<>0);
      Bitmap[ 6,Y]:=((Data1 And $04)<>0);
      Bitmap[ 7,Y]:=((Data1 And $02)<>0);
      Bitmap[ 8,Y]:=((Data1 And $01)<>0);
      Bitmap[ 9,Y]:=((Data2 And $80)<>0);
      Bitmap[10,Y]:=((Data2 And $40)<>0);
      Bitmap[11,Y]:=((Data2 And $20)<>0);
      Bitmap[12,Y]:=((Data2 And $10)<>0);
      Bitmap[13,Y]:=((Data2 And $08)<>0);
      Bitmap[14,Y]:=((Data2 And $04)<>0);
      Bitmap[15,Y]:=((Data2 And $02)<>0);
      Bitmap[16,Y]:=((Data2 And $01)<>0);
      Bitmap[17,Y]:=((Data3 And $80)<>0);
      Bitmap[18,Y]:=((Data3 And $40)<>0);
      Bitmap[19,Y]:=((Data3 And $20)<>0);
      Bitmap[20,Y]:=((Data3 And $10)<>0);
      Bitmap[21,Y]:=((Data3 And $08)<>0);
      Bitmap[22,Y]:=((Data3 And $04)<>0);
      Bitmap[23,Y]:=((Data3 And $02)<>0);
      Bitmap[24,Y]:=((Data3 And $01)<>0)
      End
End;

Procedure ScanSides(Var Bitmaps:BitmapsType; FixedX,FixedY:Boolean);
{Determines the minimal size of the Bitmap for proportional spacing}
Var X,Y:SizeRange;
Begin
With Bitmaps Do
  Begin
  If FixedX Then
    Begin 
    XMin:=1; 
    XMax:=SizeMax 
    End
  Else
    Begin
    XMin:=SizeMax1;
    For X:=SizeMax DownTo 1 Do 
      For Y:=1 To SizeMax Do 
        If Bitmap[X,Y] Then XMin:=X;
    XMax:=0;
    For X:=1 To SizeMax Do 
      For Y:=1 To SizeMax Do 
        If Bitmap[X,Y] Then XMax:=X
    End;
  If FixedY Then
    Begin 
    YMin:=1; 
    YMax:=SizeMax 
    End
  Else
    Begin
    YMin:=SizeMax1;
    For Y:=SizeMax DownTo 1 Do
      For X:=1 To SizeMax Do
        If Bitmap[X,Y] Then YMin:=Y;
    YMax:=0;
    For Y:=1 To SizeMax Do
      For X:=1 To SizeMax Do
        If Bitmap[X,Y] Then YMax:=Y
    End
  End
End;

Procedure Generate(Var InFile:InFileType; Var OutFile:OutFileType;
                   Var Number:Integer; Var RunTime:RunTimeType);
{Generates the METAFONT code for the selected font}
Var
  {Bitmap pointers}
  CurrentBitmap,WantedBitmap:Bitmap0Range;
  {Current Bitmap}
  Bitmaps:BitmapsType;
  X,Y:Size0Range;
  {Indicates early in font kanjiaa}
  First:Boolean;
  {Indicates current Bitmap is empty}
  Empty:Boolean;
Begin
{Clear the area outside the Bitmap once and for all}
With Bitmaps Do
  Begin
  For X:=0 To SizeMax1 Do 
    Begin Bitmap[X,0]:=False; Bitmap[X,SizeMax1]:=False End;
  For Y:=1 To SizeMax Do 
    Begin Bitmap[0,Y]:=False; Bitmap[SizeMax1,Y]:=False End
  End;
{Number of the Bitmap ready to be read}
CurrentBitmap:=1;
{First METAFONT character number}
Number:=0;
{First Bitmap wanted}
If RunTime.Automatic Then
  Begin
  WantedBitmap:=1024 * ( Ord(UpCase(RunTime.FileName[6]))-Ord('A') ) +
                128 * ( Ord(UpCase(RunTime.FileName[7]))-Ord('A') ) - 1;
  First:=(WantedBitmap=-1)
  End;
Repeat
  FindWantedBitmap(RunTime.Automatic,First,WantedBitmap,Number);
  If WantedBitmap<>0 Then
    Begin
    {Position pointer}
    If WantedBitmap<>CurrentBitmap Then 
      Begin
      Seek(InFile,WantedBitmap-1);
      CurrentBitmap:=WantedBitmap
      End;
    Write('Reading Bitmap');
    ScanBitmap(InFile,Bitmaps.Bitmap,Empty);
    CurrentBitmap:=CurrentBitmap+1;
    Writeln('.');
    {Process Bitmap}
    If Empty Then Writeln('Bitmap is empty, no METAFONT code ',Number,'.')
    Else
      Begin
      Write('Writing METAFONT code ',Number);
      ScanSides(Bitmaps,RunTime.FixedX,RunTime.FixedY);
      MiddleOut(OutFile,Bitmaps,Number,RunTime.Standard);
      Writeln('.')
      End;
    Writeln;
    {Ready to generate next METAFONT character}
    Number:=Number+1
    End;
Until WantedBitmap=0
End;

{------------------------------------ Main -----------------------------------}

Begin
Writeln;
Writeln('Bitmaps to METAFONT Conversion Program.');   {To make Borland happy}
Writeln('Version 2.00 Copyright F. Jalbert 1991.');
Writeln;

Write('Opening Bitmap file JIS24');
Assign(InFile,'JIS24');
Reset(InFile,RecSize);
Writeln('.');
Writeln;

GetParameters(RunTime);
Write('Creating METAFONT file '+RunTime.FileName+'.mf');
Assign(OutFile,RunTime.FileName+'.mf');
Rewrite(OutFile);
Writeln('.');
Writeln;

Write('Writing initial METAFONT header');
BeginOut(OutFile,RunTime);
Writeln('.');
Writeln;
Generate(InFile,OutFile,Number,RunTime);
Writeln;

Write('Writing final METAFONT header');
EndOut(OutFile,RunTime);
Writeln('.');
Write('Closing METAFONT file '+RunTime.FileName+'.mf');
Close(OutFile);
Writeln('.');
Write('Closing Bitmap file JIS24');
Close(InFile);
Writeln('.');
Writeln;

Writeln('METAFONT code for ',Number,' Bitmap(s) generated.');
Writeln
End.
