summaryrefslogtreecommitdiff
path: root/info/digests/texhax/txh/kesner.txh
diff options
context:
space:
mode:
Diffstat (limited to 'info/digests/texhax/txh/kesner.txh')
-rw-r--r--info/digests/texhax/txh/kesner.txh475
1 files changed, 475 insertions, 0 deletions
diff --git a/info/digests/texhax/txh/kesner.txh b/info/digests/texhax/txh/kesner.txh
new file mode 100644
index 0000000000..3beb36bc04
--- /dev/null
+++ b/info/digests/texhax/txh/kesner.txh
@@ -0,0 +1,475 @@
+Subject: Hershey fonts
+
+This submission is being sent in response to a question in texhax [#70].
+I (jok@gpu.utcs.toronto.edu) am posting this submission for my father, Oliver.
+Consequently, everything after this paragraph is written by him. I will
+accept any responses and forward them to him. His interest in TeX
+revolves around multi-lingual (hobby) desktop publishing.
+
+Hershey fonts for the IBM PC are available from SoftCraft, Inc., and from
+Austin Code Works. The SoftCraft set consists of four separate databases:
+ HERSHEY.CHR 1594 characters
+ ORIENT.CHR 758 char.
+ PERSIAN.CHR 135 char.
+ HEBREW.CHR 49 char.
+The HERSHEY.CHR database includes, besides several Roman typefaces, Greek,
+Russian, German Fraktur, and a variety of graphic symbols; the ORIENT.CHR
+database has hiragana, katakana, and 623 kanji characters.
+
+The format of the SoftCraft Hershey databases is given in their "Font Editing:
+EFONT/CFONT User's Manual" on p. A5-2. Using this description, I wrote the
+following Turbo Pascal 4.0 program to generate METAFONT source code from the
+Hershey plotter directives:
+
+HERSHEY.PAS
+-----------
+{$R-} {Range checking off}
+{$B-} {Short-circuit Boolean evaluation}
+{$S-} {Stack checking off}
+{$I+} {I/O checking on}
+{$N-} {Numeric coprocessor absent}
+{$M 65500, 16384, 655360} {Turbo 3 default stack and heap}
+
+program Hershey; {generates METAFONT source code from a Hershey character
+ database in SoftCraft format}
+const
+ NMax = 157; {maximum number of plotter pen movement commands for one
+ character in the databases}
+ PenUp = $4000;
+ EndOfChar = 0;
+var
+ H : file of integer; {Hershey database input}
+ Log : text; {METAFONT source output}
+ Code, Depth, EndChar, Height, I, J, K, N, StartChar, Width, XMax, XMin, Y0,
+ YMax, YMin : integer;
+ XY : array[0..NMax] of integer; {(x, y) coordinates}
+ Z : array[1..NMax] of byte; {METAFONT variables}
+ Database : string[7]; {database filename without extension}
+
+procedure ReadH; {reads a plotter directive from the input file}
+begin
+ if Eof(H) then
+ begin
+ Writeln('End of file at char = ', Code);
+ Close(H);
+ Close(Log);
+ Halt;
+ end;
+ Inc(N);
+ Read(H, XY[N]);
+end; {ReadH}
+
+begin
+ if ParamCount <> 3 then
+ begin
+ Writeln('Usage: HERSHEY database start end');
+ Halt;
+ end;
+ Database := ParamStr(1);
+ for Code := 1 to 7 do
+ Database[Code] := UpCase(Database[Code]);
+ Val(ParamStr(2), StartChar, Code);
+ if Code <> 0 then
+ begin
+ Writeln('Starting character not an integer');
+ Halt;
+ end;
+ Val(ParamStr(3), EndChar, Code);
+ if Code <> 0 then
+ begin
+ Writeln('Ending character not an integer');
+ Halt;
+ end;
+ Assign(H, Database + '.CHR');
+ Reset(H);
+ Assign(Log, Database + '.LOG');
+ Rewrite(Log);
+ Writeln(Log, '% ', Database + '.CHR ', StartChar, ' to ', EndChar);
+ for Code := 0 to StartChar do
+ begin
+ N := -1;
+ repeat
+ ReadH;
+ until XY[N] = EndOfChar;
+ end; {skip forward to specified start character}
+ Z[1] := 1;
+ for Code := StartChar to EndChar do
+ begin
+ Writeln(Log);
+ Writeln(Log, 'cmchar "', Database, ' ', Code, '";');
+ N := -1;
+ ReadH; {the width bytes}
+ XMin := Lo(XY[0]); {minimum x coordinate}
+ XMax := Hi(XY[0]); {maximum x coordinate}
+ Width := XMax - XMin; {width of character}
+ Y0 := 73; {default y bias}
+ if Database = 'HERSHEY' then
+ case Code of
+ 0..88: Y0 := 68;
+ 397..672: Y0 := 70;
+ end;
+ {Find minimum and maximum y values.}
+ YMax := 0;
+ YMin := 256;
+ repeat
+ ReadH;
+ if (XY[N] <> PenUp) and (XY[N] <> EndOfChar) then
+ begin
+ if Hi(XY[N]) > YMax then
+ YMax := Hi(XY[N]);
+ if Hi(XY[N]) < YMin then
+ YMin := Hi(XY[N]);
+ end; {if a real coordinate}
+ until XY[N] = EndOfChar;
+ Height := Y0 - YMin;
+ if YMax > Y0 then
+ Depth := YMax - Y0
+ else
+ Depth := 0;
+ Writeln(Log, 'beginchar(', Code mod 128, ', ', Width, 'u#, ', Height,
+ 'u#, ', Depth, 'u#);');
+ Writeln(Log, 'adjust_fit(0, 0);');
+ Writeln(Log, 'pickup plotter_pen;');
+ for I := 2 to Pred(N) do
+ begin {enumerate unique coordinates}
+ Z[I] := 0;
+ if XY[I] <> PenUp then
+ begin
+ for J := Pred(I) downto 1 do
+ if XY[I] = XY[J] then
+ Z[I] := J;
+ if Z[I] = 0 then
+ Z[I] := I;
+ end;
+ end;
+ for I := 1 to Pred(N) do
+ if Z[I] = I then
+ Writeln(Log, 'z', I, ' = (', Lo(XY[I]) - XMin, 'u, ', Y0 - Hi(XY[I]),
+ 'u);');
+ I := 0;
+ J := 1;
+ repeat
+ Inc(I);
+ if (XY[I] = PenUp) or (XY[I] = EndOfChar) then
+ begin
+ case I - J of {number of points joined by consecutive line segments}
+ 0: ;
+ 1: Writeln(Log, 'drawdot z', Z[J], ';');
+ 2: if Z[J] = Z[Succ(J)] then
+ Writeln(Log, 'drawdot z', Z[J], ';')
+ else
+ Writeln(Log, 'draw z', Z[J], '--z', Z[Succ(J)], ';');
+ else
+ begin
+ Write(Log, 'draw z', Z[J]);
+ for K := Succ(J) to Pred(I) do
+ Write(Log, '--z', Z[K]);
+ Writeln(Log, ';');
+ end; {3 or more}
+ end; {case}
+ J := Succ(I);
+ end; {if a real coordinate}
+ until I = N;
+ Writeln(Log, 'endchar;');
+ end; {specified range of characters}
+ Close(H);
+ Close(Log);
+end.
+
+As a test case I used the DOS command
+ hershey orient 0 1
+to produce the following output:
+
+ORIENT.LOG
+----------
+% ORIENT.CHR 0 to 1
+
+cmchar "ORIENT 0";
+beginchar(0, 27u#, 12u#, 0u#);
+adjust_fit(0, 0);
+pickup plotter_pen;
+z1 = (3u, 10u);
+z2 = (25u, 10u);
+z3 = (22u, 12u);
+z4 = (20u, 10u);
+z7 = (23u, 11u);
+draw z1--z2--z3--z4;
+draw z4--z7;
+endchar;
+
+cmchar "ORIENT 1";
+beginchar(1, 27u#, 22u#, 0u#);
+adjust_fit(0, 0);
+pickup plotter_pen;
+z1 = (3u, 20u);
+z2 = (25u, 20u);
+z3 = (23u, 22u);
+z4 = (21u, 20u);
+z7 = (24u, 21u);
+z9 = (13u, 20u);
+z10 = (12u, 13u);
+z11 = (11u, 9u);
+z12 = (10u, 7u);
+z13 = (8u, 4u);
+z14 = (6u, 2u);
+z15 = (3u, 0u);
+z17 = (14u, 20u);
+z18 = (13u, 13u);
+z19 = (12u, 9u);
+z20 = (10u, 5u);
+z21 = (8u, 3u);
+z22 = (5u, 1u);
+z25 = (13u, 14u);
+z26 = (21u, 14u);
+z28 = (20u, 14u);
+z29 = (21u, 15u);
+z30 = (23u, 14u);
+z31 = (21u, 11u);
+z34 = (20u, 7u);
+z35 = (19u, 3u);
+z36 = (18u, 2u);
+z37 = (16u, 1u);
+z38 = (13u, 2u);
+z40 = (19u, 2u);
+z41 = (18u, 1u);
+z42 = (17u, 1u);
+z44 = (22u, 14u);
+z45 = (21u, 7u);
+z46 = (20u, 3u);
+z47 = (19u, 1u);
+z48 = (18u, 0u);
+z49 = (17u, 0u);
+draw z1--z2--z3--z4;
+draw z4--z7;
+draw z9--z10--z11--z12--z13--z14--z15;
+draw z17--z18--z19--z20--z21--z22--z15;
+draw z25--z26;
+draw z28--z29--z30--z31;
+draw z26--z34--z35--z36--z37--z38;
+draw z40--z41--z42;
+draw z44--z45--z46--z47--z48--z49--z37;
+endchar;
+
+
+I used the following METAFONT parameter file:
+
+ORIENT.MF
+---------
+% This is ORIENT.MF in text format, as of May 6, 1988.
+% Based on Computer Modern Roman 10 point
+if unknown cmbase: input cmbase fi
+
+font_identifier:="ORIENT"; font_size 10pt#;
+
+u#:=20/36pt#; % unit width
+width_adj#:=0pt#; % width adjustment for certain characters
+serif_fit#:=0pt#; % extra sidebar near lowercase serifs
+cap_serif_fit#:=5/36pt#; % extra sidebar near uppercase serifs
+letter_fit#:=0pt#; % extra space added to all sidebars
+
+body_height#:=270/36pt#; % height of tallest characters
+asc_height#:=250/36pt#; % height of lowercase ascenders
+cap_height#:=246/36pt#; % height of caps
+fig_height#:=232/36pt#; % height of numerals
+x_height#:=155/36pt#; % height of lowercase without ascenders
+math_axis#:=90/36pt#; % axis of symmetry for math symbols
+bar_height#:=87/36pt#; % height of crossbar in lowercase e
+comma_depth#:=70/36pt#; % depth of comma below baseline
+desc_depth#:=70/36pt#; % depth of lowercase descenders
+
+crisp#:=0pt#; % diameter of serif corners
+tiny#:=8/36pt#; % diameter of rounded corners
+fine#:=7/36pt#; % diameter of sharply rounded corners
+thin_join#:=7/36pt#; % width of extrafine details
+hair#:=9/36pt#; % lowercase hairline breadth
+stem#:=25/36pt#; % lowercase stem breadth
+curve#:=30/36pt#; % lowercase curve breadth
+ess#:=27/36pt#; % breadth in middle of lowercase s
+flare#:=33/36pt#; % diameter of bulbs or breadth of terminals
+dot_size#:=38/36pt#; % diameter of dots
+cap_hair#:=11/36pt#; % uppercase hairline breadth
+cap_stem#:=32/36pt#; % uppercase stem breadth
+cap_curve#:=37/36pt#; % uppercase curve breadth
+cap_ess#:=35/36pt#; % breadth in middle of uppercase s
+rule_thickness#:=.4pt#; % thickness of lines in math symbols
+
+dish#:=1/36pt#; % amount erased at top or bottom of serifs
+bracket#:=20/36pt#; % vertical distance from serif base to tangent
+jut#:=28/36pt#; % protrusion of lowercase serifs
+cap_jut#:=37/36pt#; % protrusion of uppercase serifs
+beak_jut#:=10/36pt#; % horizontal protrusion of beak serifs
+beak#:=70/36pt#; % vertical protrusion of beak serifs
+vair#:=8/36pt#; % vertical diameter of hairlines
+notch_cut#:=10pt#; % maximum breadth above or below notches
+bar#:=11/36pt#; % lowercase bar thickness
+slab#:=11/36pt#; % serif and arm thickness
+cap_bar#:=11/36pt#; % uppercase bar thickness
+cap_band#:=11/36pt#; % uppercase thickness above/below lobes
+cap_notch_cut#:=10pt#; % max breadth above/below uppercase notches
+serif_drop#:=4/36pt#; % vertical drop of sloped serifs
+stem_corr#:=1/36pt#; % for small refinements of stem breadth
+vair_corr#:=1/36pt#; % for small refinements of hairline height
+apex_corr#:=0pt#; % extra width at diagonal junctions
+
+o#:=8/36pt#; % amount of overshoot for curves
+apex_o#:=8/36pt#; % amount of overshoot for diagonal junctions
+
+slant:=0; % tilt ratio $(\Delta x/\Delta y)$
+fudge:=1; % factor applied to weights of heavy characters
+math_spread:=0; % extra openness of math symbols
+superness:=1/sqrt2; % parameter for superellipses
+superpull:=1/6; % extra openness inside bowls
+beak_darkness:=11/30; % fraction of triangle inside beak serifs
+ligs:=2; % level of ligatures to be included
+
+square_dots:=false; % should dots be square?
+hefty:=false; % should we try hard not to be overweight?
+serifs:=true; % should serifs and bulbs be attached?
+monospace:=false; % should all characters have the same width?
+variant_g:=false; % should an italic-style g be used?
+low_asterisk:=false; % should the asterisk be centered at the axis?
+math_fitting:=false; % should math-mode spacing be used?
+
+font_coding_scheme:="Hershey ORIENT.CHR";
+
+mode_setup; font_setup;
+
+px#:=rule_thickness#; % horizontal thickness of pen
+py#:=.9px#; % vertical pen thickness
+define_blacker_pixels(px,py);
+pickup pencircle xscaled px yscaled py;
+plotter_pen:=savepen;
+input \ff\orient.log
+
+font_slant slant; font_x_height x_height#;
+if monospace: font_normal_space 9u#; % no stretching or shrinking
+ font_quad 18u#;
+ font_extra_space 9u#;
+else: font_normal_space 6u#+2letter_fit#;
+ font_normal_stretch 3u#; font_normal_shrink 2u#;
+ font_quad 18u#+4letter_fit#;
+ font_extra_space 2u#; fi
+bye.
+
+The following sequence of DOS commands
+ cd\ff
+ hershey orient 0 127
+ cd\pcmf
+ mf &cm \mode=epson; \mag=magstep 0; input orient /a=99/t
+produced ORIENT.240 and ORIENT.TFM in \pcmf for my Epson FX-85 printer,
+containing the first 128 characters of ORIENT.CHR.
+
+The characters in the Austin Code Works Hershey database are numbered 1--4326,
+with gaps, for a total of 1,377 different alphabetic and graphic characters.
+The format is described in Norman M. Wolcott and Joseph Hilsenrath, "A
+Contribution to Computer Typesetting Techniques: Tables of Coordinates for
+Hershey's Repertory of Occidental Type Fonts and Graphic Symbols," U.S.
+Department of Commerce, National Bureau of Standards, April 1976. In any case,
+the following Turbo Pascal 4.0 program converts the ACW Hershey database to
+SoftCraft format for further processing.
+
+ACWTOSC.PAS
+-----------
+{$R-} {Range checking off}
+{$B-} {Short-circuit Boolean evaluation}
+{$S-} {Stack checking off}
+{$I+} {I/O checking on}
+{$N-} {No numeric coprocessor}
+{$M 65500, 16384, 655360} {Turbo 3 default stack and heap}
+
+program ACWtoSC; {converts the Hershey font tables distributed by The Austin
+ Code Works to the format expected by the Cfont program of SoftCraft, Inc.}
+const
+ PenUp : integer = $4000;
+type
+ S3 = string[3];
+var
+ Buf1 : array[1..$2000] of char;
+ F1 : text;
+ H : file of integer;
+ L1 : string[80];
+ Fn : array[1..2] of string[64];
+ Code, I, L, M, XY : integer;
+ X, Y : array[1..144] of integer;
+ Eoc : boolean;
+
+function V(S : S3) : integer;
+var
+ I : integer;
+begin
+ Val(S, I, Code);
+ if (Code <> 0) or ((I < -49) and (I <> -64)) or (I > 49) then
+ begin
+ Writeln(L1);
+ Writeln('Code = ', Code);
+ Halt(3);
+ end;
+ V := I;
+end;
+
+begin
+ if ParamCount <> 2 then
+ begin
+ Writeln('Usage: ACWTOSC file1 file2');
+ Halt(3);
+ end;
+ for L := 1 to 2 do
+ begin
+ Fn[L] := ParamStr(L);
+ for M := 1 to Length(Fn[L]) do
+ Fn[L][M] := UpCase(Fn[L][M]);
+ end;
+ Assign(F1, Fn[1]);
+ SetTextBuf(F1, Buf1);
+ {$I-} Reset(F1); {$I+}
+ if IOResult <> 0 then
+ begin
+ Writeln('Cannot open ', Fn[1]);
+ Halt(3);
+ end;
+ Assign(H, Fn[2]);
+ {$I-} Rewrite(H); {$I+}
+ if IOResult <> 0 then
+ begin
+ Writeln('Cannot open ', Fn[2]);
+ Close(F1);
+ Halt(3);
+ end;
+ while not Eof(F1) do
+ begin
+ Readln(F1, L1);
+ if Copy(L1, 5, 1) <> ' ' then
+ begin
+ M := 0;
+ Eoc := false;
+ end;
+ L := 0;
+ repeat
+ Inc(L);
+ Inc(M);
+ X[M] := V(Copy(L1, 8 * L + 1, 3));
+ Y[M] := V(Copy(L1, 8 * L + 5, 3));
+ if (X[M] = -64) and (Y[M] = -64) then
+ begin
+ Eoc := true;
+ Write(H, Code); {two bytes of zeros before each character}
+ XY := 256 * (Y[1] + 64) + X[1] + 64; {width of character}
+ Write(H, XY);
+ for I := 2 to Pred(M) do
+ if X[I] = -64 then
+ Write(H, PenUp)
+ else
+ begin
+ XY := 256 * (73 + Y[I]) + X[I] + 64;
+ Write(H, XY);
+ end;
+ end;
+ until (L = 8) or Eoc;
+ end;
+ Write(H, Code); {two bytes of zeros at end of file}
+ Close(F1);
+ Close(H);
+end.
+
+-------
+