§1  hbf2gf (CJK Version 4.8.3)  INTRODUCTION 1

1. Introduction. This is the  program by Werner Lemberg (  ).

The “banner line” defined here should be changed whenever is modified.

#define banner  ␣    ␣    ␣

2  INTRODUCTION  hbf2gf (CJK Version 4.8.3) §2

2. is intended to convert Hanzi Bitmap Fonts (HBF) into TEX generic font files ( files) according to the CJK package, which is part of.

The outline of is simple: a CJK (Chinese/Japanese/Korean) bitmap file will be scaled and written in at most nmb files files, each file containing 256 characters (except the last and possibly the first one). In the normal case it’s not necessary to compute the right value of nmb files because will do this; you should use −1 instead to indicate this. See the last section for an example.

Alternatively you can call similar to , i.e., the program will compute one font on demand. This mode will be used if two or three input parameters instead of one are given: the font name, the horizontal resolution, and optionally a vertical scaling factor or resolution to allow modes for e.g. 300 × 600 dpi printers. will extract the configuration file name from the font name; if this file isn’t found, the program exits with error code 2 (this is useful for scripts like ). If the configuration file is found but an error occurs while computing the font, error code 1 is returned. In case of success, the exit code is zero.

The characters in the input font files are completely described by the HBF header file. This program uses the HBF API implementation of Ross Paterson ( ; with small extensions). You will find a description of the HBF standard at .

A batch file created by too (if the program computes a whole set of subfonts) will convert the files to files using , a part of every TEX package.

#define  1
#define  0
#define  255

/∗ the maximal length of an input string in the configuration file ∗/

#define  1024  /∗ the maximal length (including the path) of a filename ∗/

⟨ Global variables 2 ⟩ ≡ int nmb files = −1; /∗ create all files by default ∗/

int unicode =  ;  /∗ whether a Unicode font should be processed ∗/
int testing =  ;  /∗ whether we test only the font name ∗/
int mf like =  ;  /∗ whether we are in the  -like mode ∗/

int file number = 0; /∗ the subfont number ∗/

double x resolution = 0.0; /∗ the second and third input parameter ∗/

double y scale = 1.0;

int pk files = ; /∗ command line options ∗/

int tfm files = ;

int long extension = ;

int quiet = ;

char config file[ + 4 + 1]; /∗ we probably must add ‘ ’ ∗/

char output name[ + 1];

FILE ∗config , ∗out ;

HBF ∗hbf ; #ifdef /∗ if we compile under DOS or OS/2 ∗/ #define #define #define #define #else #define #define #define #define #endif

int end of file = ;

See also sections 15, 19, 27, 38, 49, 53, 58, 60, 62, 70, 73, and 76. This code is used in section 4.

3. One file will be created additionally, which describes the font metrics in a readable way. Because all CJK characters have identical bounding boxes, one metrics file is enough—the batch job created by calls to produce this file and then copies it into nmb files metrics files. There usually will be a discrepancy between the number of characters in the last file and the file, but this does not harm.

If you specify the option in the configuration file, an extended virtual property file (such

files have the extension  ) for the Ω system is written; this will be then converted with  into
an  and an  file to map all the subfonts into one large virtual font.

4  THE MAIN ROUTINE  hbf2gf (CJK Version 4.8.3) §4

4. The main routine. The main routine takes file name, x resolution, and y scale as command line parameters if in -like mode, otherwise config file as the only argument. read config ( ) scans the configuration file and fills the global variables, write file( ) writes the files, write pl ( ) and write ovp( ) write the and files respectively, and write job( ) the batch file.

⟨ Include files 10 ⟩ ⟨ Prototypes 11 ⟩ ⟨ Global variables 2 ⟩ int main(int argc, char ∗argv [ ]) {

char ∗p; ⟨ Initialize TEX file searching 78 ⟩ ⟨ Scan options 7 ⟩ if (¬quiet ) printf ( , banner ); strncpy (config file, argv [1], ); config file[ ] = ; if (argc > 2 ∨ testing ) {

int l = strlen(config file);

if (l > 2) config file[l − 2] = ; /∗ strip subfont number from file name ∗/ else {

if (¬quiet ) printf ( ␣ ␣ ␣ ␣ ␣ ␣ ␣ , config file); exit (2);

}

mf like = ; } read config ( ); /∗ will call exit (1) on errors ∗/ if (mf like) ⟨ Check other arguments 8 ⟩ ⟨ Initialize variables 28 ⟩ ⟨ Write files 9 ⟩ if (tfm files ) write pl ( ); if (ofm file) write ovp( ); if (¬mf like) write job( ); hbfClose(hbf ); exit (0); return 0; /∗ never reached ∗/

§5  hbf2gf (CJK Version 4.8.3)  THE MAIN ROUTINE 5

} 5.

#define

␣   ␣         ␣      ␣
␣  ␣  ␣         ␣␣   ␣   ␣            ␣    ␣
␣   ␣     ␣  ␣    ␣   ␣       ␣       ␣
␣   ␣   ␣       ␣
␣    ␣           ␣     ␣     ␣        ␣   ␣   ␣
␣       ␣   ␣

⟨ Print version 5 ⟩ ≡

{ printf ( ); printf (banner ); printf ( ␣ , TeX search version( )); printf ( ); exit (0);

}

This code is used in section 7.

6.

#define

␣      ␣    ␣
␣␣␣␣␣␣␣      ␣         ␣         ␣            ␣        ␣ ␣
␣␣␣␣␣␣␣      ␣  ␣    ␣
␣␣       ␣ ␣    ␣   ␣   ␣      ␣  ␣      ␣  ␣     ␣  ␣
␣␣␣␣␣␣␣␣␣  ␣␣␣␣␣␣␣␣␣␣␣␣␣  ␣
␣␣␣␣␣␣␣␣␣  ␣␣␣␣␣␣␣␣␣␣␣␣␣     ␣       ␣  ␣  ␣
␣␣␣␣␣␣␣␣␣  ␣␣␣␣␣␣␣␣␣␣␣␣␣     ␣       ␣  ␣  ␣
␣␣␣␣␣␣␣␣␣  ␣␣␣␣␣␣␣␣␣␣␣␣␣   ␣  ␣          ␣  ␣         ␣      ␣
␣␣␣␣␣␣␣␣␣  ␣␣␣␣␣␣␣␣␣␣␣␣␣    ␣   ␣         ␣        ␣ ␣  ␣
␣␣␣␣␣␣␣␣␣      ␣␣␣␣␣␣␣␣␣     ␣    ␣       ␣   ␣
␣␣␣␣␣␣␣␣␣         ␣␣␣␣␣␣     ␣       ␣      ␣   ␣

⟨ Print help information 6 ⟩ ≡

{ printf ( ); exit (0);

}

This code is used in section 7.

7. Three options can be specified to the program ( , , and ) if in -like mode to suppress creation of a resp. a file, and to force a ‘ ’ extension (instead of e.g. ‘ ’). The corresponding setting of a particular switch in the configuration file is ignored then.

Additionally, the option tests whether the specified subfont name leads to an configuration file. It returns 0 on success and prints out the name of that configuration file (provided the switch isn’t set). This test isn’t a thorough one; it only removes the last two characters and checks whether a configuration file with that name exists. ⟨ Scan options 7 ⟩ ≡

if (argc ≡ 2) { if (strcmp(argv [1], ) ≡ 0) ⟨ Print help information 6 ⟩ else if (strcmp(argv [1], ) ≡ 0) ⟨ Print version 5 ⟩

} while (argc > 1) {

p = argv [1]; if (p[0] ≠ ) break; if (p[1] ≡ ) tfm files = ; else if (p[1] ≡ ) pk files = ; else if (p[1] ≡ ) long extension = ; else if (p[1] ≡ ) quiet = ; else if (p[1] ≡ ) testing = ; argv^{++}; argc^{−};

} if (testing ) {

if (argc ≠ 2) {

fprintf (stderr ,  ␣       ␣   ␣         ␣   ␣    ␣  );
fprintf (stderr ,  ␣       ␣        ␣   ␣    ␣  );

exit (1); }

} else if (argc < 2 ∨ argc > 4) {

fprintf (stderr ,  ␣      ␣  ␣  );
fprintf (stderr ,  ␣       ␣        ␣   ␣    ␣  );

exit (1); }

This code is used in section 4.

8. If the (optional) argument is larger than 10, we treat it as a value for the vertical resolution (in dpi), otherwise as a vertical scaling factor. ⟨ Check other arguments 8 ⟩ ≡

{ if (unicode) file number = (int) strtol (&argv [1][strlen(argv [1]) − 2], (char ∗∗) Λ, 16); else file number = atoi (&argv [1][strlen(argv [1]) − 2]); x resolution = atof (argv [2]); if (x resolution < ) {

fprintf (stderr , ␣ ␣ ); exit (1);

} if (argc > 3) {

y scale = atof (argv [3]);

if (y scale < 0.01) { fprintf (stderr , ␣ ␣ ␣ ␣ ␣ ); exit (1);

}

if (y scale > 10.0) y scale = (double) x resolution/y scale; }

}

This code is used in section 4.

9. If unicode is , the start value of the running number appended to the base name of the output font files is taken from the HBF header file, otherwise it starts with ‘ ’. min char represents the lower bound of the code range.

If we are in -like mode, file number is taken from the command line, and max numb will be set to 1. ⟨ Write files 9 ⟩ ≡

{ int j, max numb; if (¬mf like) {

file number = (unicode ≡ ? (min char ≫ 8) : 1);

if (nmb files ≡ −1) max numb = (unicode ≡ ? ^{#}100 : 100); else max numb = nmb files ;

} else max numb = 1; for (j = 0; (j < max numb) ∧ ¬end of file; file number^{++}, j^{++}) write file( ); nmb files = j; /∗ the real number of output font files ∗/

}

This code is used in section 4.

10. ⟨ Include files 10 ⟩ ≡ #ifdef #include #endif #include #include #include #include #include #ifdef #include #endif #include

See also section 69. This code is used in section 4.

§11  hbf2gf (CJK Version 4.8.3)  THE FUNCTIONS 9

11. The functions. The first function to be described is write file( ). Each file consists of three sections: a preamble, a data section, and a postamble. The functions write pre( ), write data( ), and write post ( ) handle this. ⟨ Prototypes 11 ⟩ ≡

static void write file(void);

See also sections 13, 16, 20, 25, 29, 36, 39, 41, 45, 47, 50, 54, 64, 67, 71, 74, and 79. This code is used in section 4.

12. In  -like mode we create font file name extensions similar to  if the

option isn’t specified; otherwise only ‘ ’ will be appended.

static void write file(void)

{ char output file[ + 1]; if (pk files ) { if (mf like) {

if (unicode) sprintf (output file, ,

output name, file number , long extension ? (int)(x resolution + 0.5) : 0); else sprintf (output file, ,

output name, file number , long extension ? (int)(x resolution + 0.5) : 0); } else {

if (unicode) sprintf (output file, , output name, file number ); else sprintf (output file, , output name, file number );

}

if (¬(out = fopen(output file, ))) { fprintf (stderr , ␣ ␣ , output file); exit (1);

}

if (¬quiet ) printf ( ␣ ␣ , output file); write pre( ); write data( ); write post ( ); fclose(out ); if (¬quiet ) printf ( );

}

else write data( ); }

13. The preamble has two bytes at the very beginning,  and  .  starts the preamble, and

is the Generic Font Identity Byte. The next bytes are a string in Pascal format containing a header, the date, and the time. Strings in Pascal format start with the length of the string and have no terminating NULL byte.

#define  131
#define  247
#define headertstring ␣      ␣      ␣

10  THE FUNCTIONS  hbf2gf (CJK Version 4.8.3) §14

⟨ Prototypes 11 ⟩ +≡ static void write pre(void); 14.

static void write pre(void) {

char out s [40], s[20]; time t secs now ; struct tm ∗time now ; strcpy (out s , headertstring ); secs now = time(Λ); /∗ system date and time ∗/ time now = localtime(&secs now ); strftime(s, 20, , time now ); strcat (out s , s); fputc( , out ); fputc( , out ); fputc(strlen(out s ), out ); fputs (out s , out );

} 15. write data( ) produces the middle part of the file. It first sets char adr p equal to the address of char adr [ ] which will contain file offsets of the compressed characters.

input size x and input size y reflect the original dimensions of the bitmap font, pk output size x and pk output size y contain the width and height of the output character box (in pixels), pk offset x and pk offset y define the baseline of the font. The same names starting with ‘tfm ’ instead of ‘pk ’ are used for files (values are multiples of design size). mag x and mag y hold the scaling factors which are needed to reach design size. slant defines the slant (Δx/Δy), target size x and target size y will be the final dimensions; magstep x = target size x /design size is TEX’s .

The C standard specifies that all global values will be automatically set to 0 if no initialization value is given. ⟨ Global variables 2 ⟩ +≡

long char adr [256]; long ∗char adr p; int pk offset x ; /∗ horizontal offset (increase character width a bit; will be applied on both the

left and the right side) ∗/ double tfm offset x ; int pk offset y ; /∗ vertical offset (must be configured to desired font size) ∗/ double tfm offset y ; int input size x ; int input size y ; const char ∗font encoding ; /∗ taken from the HBF file ∗/ int pk width; /∗ without slant ∗/ int pk output size x ; /∗ the output character box dimensions without offsets ∗/ double tfm output size x ; int pk output size y ; double tfm output size y ; double design size = 10.0; /∗ in points ∗/ double target size x ; /∗ in points ∗/ double target size y ; double magstep x ; double magstep y ; double slant ; int rotation; double mag x ; /∗ horizontal and vertical magnification values ∗/ double mag y ; int empty char ; /∗ a flag whether the character does not exist or is empty ∗/ int last char ; /∗ the last valid character in a file ∗/ int dot count ;

/∗ this counts the processed characters; every ten characters a dot is output to the screen ∗/

16. ⟨ Prototypes 11 ⟩ +≡

static void write data(void); 17.

static void write data(void) {

dot count = 0;

char adr p = char adr ;

for (last char = 0; (last char < 256) ∧ ¬end of file; last char^{++}) ⟨ Write character 18 ⟩ } 18. The code in this section saves the current file position first and calls make pixel array ( ), which expands and scales the character bitmap.

(and ), the Begin Of Character command byte, must be followed by the character code and the dimensions of the character as explained in “ —the program” (corrected by vertical and horizontal offsets).

write coding ( ) compresses and outputs the bitmap; (End Of Character) finishes the current character.

#define  67

#define 68 /∗ simplified version of ∗/

#define  69

⟨ Write character 18 ⟩ ≡

{

if (dot count^{++} % 10 ≡ 0) /∗ a progress report for impatient users ∗/

if (pk files ∧ ¬quiet ) { printf ( ); fflush(stdout );

} empty char = ; make pixel array ( ); if (end of file) return; if (pk files ) {

∗char adr p = ftell (out ); char adr p^{++}; if (empty char ) {

fputc( , out ); fputc((unsigned char) last char , out ); fputc(0, out ); fputc(0, out ); fputc(0, out ); fputc(0, out ); fputc( , out );

} else {

fputc( , out ); fputl (last char , out ); fputl (−1_{L}, out ); fputl (pk offset x , out ); fputl (pk output size x + pk offset x , out ); fputl (pk offset y , out ); fputl (pk output size y + pk offset y , out ); write coding ( ); fputc( , out );

} }

}

This code is used in section 17.

19. The current file will be completed with data written by write post ( ). The end consists of three sections: “special”, “post”, and “postpost”. The first contains material not used by TEX itself but which can be used by other programs like or for documentary purposes (coding [ ] and comment [ ]). The second describes the font as a whole, and the last marks the end of the file.

pk total min x up to pk total max y define the greatest bounding box of this file (including offsets); the horizontal character escapement after drawing the character is pk dx . tfm width is the width in multiples of the design size ignoring the target size.

#define  65536.0  /∗ 2^{16} ∗/
#define  1048576.0  /∗ 2^{20} ∗/

⟨ Global variables 2 ⟩ +≡

char coding [  + 1];  /∗ a comment describing the font encoding ∗/
char comment [  + 1];  /∗ a comment describing the font ∗/

unsigned long checksum; long pk total min x ; long pk total max x ; long pk total min y ; long pk total max y ; int dpi x ; /∗ printer resolution ∗/ int dpi y ; double ppp x ; /∗ pixels per point ∗/ double ppp y ;

20. To clarify the meaning of these values see the sections about the metrics and configuration file also.

TEX defines that 72.27 points are exactly 1 inch. ⟨ Prototypes 11 ⟩ +≡

static void write post (void); 21.

static void write post (void) {

long special adr ; long post adr ; long designsize = design size ∗ ; /∗ design size ∗2^{20} ∗/ int pk dx ; long tfm width; int i; long temp; ppp x = dpi x /72.27 ∗ magstep x ; ppp y = dpi y /72.27 ∗ magstep y ; pk total min x = pk offset x ; pk total max x = pk output size x + 2 ∗ pk offset x ; pk total min y = pk offset y ; pk total max y = pk output size y + pk offset y ; pk dx = pk width + 2 ∗ pk offset x ; /∗ no slant ∗/ tfm width = (tfm output size x + 2 ∗ tfm offset x ) ∗ ;

/∗ width in multiples of design size ∗2^{20} ∗/ ⟨ Special section 22 ⟩ ⟨ Post section 23 ⟩ ⟨ Postpost section 24 ⟩

}

22. will be followed by n bytes representing the length of a string which follows immediately. is a 32 bit integer which is normally connected with the preceding string (but not used here). special adr contains the address of the “special section”. All items here are optional.

#define  239  /∗ these are all special command bytes ∗/
#define  240  /∗ not used ∗/
#define  241  /∗ not used ∗/
#define  242  /∗ not used ∗/
#define  243  /∗ not used ∗/

⟨ Special section 22 ⟩ ≡ special adr = ftell (out ); if (∗coding ) {

fputc( , out ); /∗ implies a string length < 256 ∗/ fputc(strlen(coding ), out ); fputs (coding , out );

} if (∗comment ) {

fputc( , out ); fputc(strlen(comment ), out ); fputs (comment , out );

}

This code is used in section 21.

23. All character offsets collected in char adr will be written to the output file. fputl ( ) writes a 32 bit integer into a file.

(and ) is the first byte of a character locator (i.e., offset, character code, and width information). starts the postamble, and post adr points to the beginning byte of the postamble.

#define  248
#define  245

#define 246 /∗ simplified version of ∗/ ⟨ Post section 23 ⟩ ≡

post adr = ftell (out ); fputc( , out ); fputl (special adr , out ); fputl (designsize, out ); fputl (checksum, out ); fputl (ppp x ∗ , out ); fputl (ppp y ∗ , out ); fputl (pk total min x , out ); fputl (pk total max x , out ); fputl (pk total min y , out ); fputl (pk total max y , out ); char adr p = char adr ; if (pk dx < 256) {

for (i = 0; i < last char ; i^{++}) /∗ the character locators ∗/ {

fputc( , out ); fputc(i, out ); fputc(pk dx , out ); fputl (tfm width, out ); fputl (∗char adr p^{++}, out );

} } else /∗ will only happen if ≥ 256 ∗/ {

for (i = 0; i < last char ; i^{++}) { fputc( , out ); fputc(i, out ); fputl (pk dx ∗ , out ); fputl (0, out ); fputl (tfm width, out ); fputl (∗char adr p^{++}, out );

} }

This code is used in section 21.

24. starts the section after the postamble. To get all information in a file, you must start here. The very last bytes of the file have the value (the file is filled with at least 4 of these bytes until a file length of a multiple of 4 is reached). Going backwards a will be next, then comes the address of the postamble section.

Jumping to the postamble, a byte comes first, then the address of the special section, and afterwards all character offsets. These offsets and addresses describe the whole file.

#define  249
#define  223

⟨ Postpost section 24 ⟩ ≡ fputc( , out ); fputl (post adr , out ); fputc( , out ); temp = ftell (out ); i = (int)(temp % 4) + 4; while (i^{−}) fputc( , out );

This code is used in section 21.

25. TEX wants the most significant byte first. ⟨ Prototypes 11 ⟩ +≡

static void fputl (long, FILE ∗);

26.

static void fputl (long num, FILE ∗f)

{ fputc(num ≫ 24, f); fputc(num ≫ 16, f); fputc(num ≫ 8, f); fputc(num, f);

} 27. make pixel array ( ) scales a character into the array out char [ ] where each byte represents one pixel, contrary to the input file where each bit is used to store the character bitmap. indicates a black pixel.

The scaling routine was modeled after the program of the package. was designed to handle arbitrary pictures, and bitmaps are only a special case of a graymap with values from 0 for white up to = 255 for black.

If is encountered, end of file is set and the function returns immediately.

#define  1
#define  0
#define  255
#define  4096
#define  2048
#define  1023

⟨ Global variables 2 ⟩ +≡ HBF CHAR code; const unsigned char ∗bitmap;

/∗ a proper input bitmap array will be allocated by the HBF API ∗/ const unsigned char ∗bP ; unsigned char out char [ ∗ + 1]; /∗ the output bitmap array ∗/ unsigned char ∗out char p; unsigned char pixelrow [ ]; unsigned char temp pixelrow [ ]; unsigned char new pixelrow [ + 1]; /∗ we need space to append a white pixel ∗/ int curr row ; /∗ for read row ( ) if we access the glyph rotated ∗/ long grayrow [ ]; long s mag x , s mag y , s slant ; 28. We need to initialize the grayrow [ ] array together with some other variables.

Two steps are necessary to compute the code if we are in the -like mode. Assuming that we search the code , we first set code to the value , where is equal to min 2 byte (getting offset as the number of remaining characters to reach the first character in our given subfont), then we increment code (and decrement offset ) until offset equals 0. ⟨ Initialize variables 28 ⟩ ≡

{ int col , offset ; if (rotation) {

int tmp;

tmp = input size x ;

input size x = input size y ;

input size y = tmp; } if (mf like) {

target size x = design size ∗ (x resolution/dpi x );

target size y = design size ∗ (x resolution ∗ y scale/dpi y ); } else target size x = target size y = design size; magstep x = target size x /design size; magstep y = target size y /design size; pk offset x = offset x ∗ magstep x + 0.5; pk offset y = offset y ∗ magstep y + 0.5; tfm offset x = offset x /(dpi x /72.27)/design size; tfm offset y = offset y /(dpi y /72.27)/design size; pk width = input size x ∗ mag x ∗ magstep x + 0.5; /∗ without slant ∗/ pk output size x = input size x ∗ mag x ∗ magstep x + input size y ∗ mag y ∗ magstep y ∗ slant + 0.5; pk output size y = input size y ∗ mag y ∗ magstep y + 0.5; tfm output size x = input size x ∗ mag x /(dpi x /72.27)/design size; tfm output size y = input size y ∗ mag y /(dpi y /72.27)/design size; if (pk output size x > ) {

fprintf (stderr , ␣ ␣ ␣ ␣ ␣ ); exit (1);

} if (pk output size y > ) {

fprintf (stderr , ␣ ␣ ␣ ␣ ␣ ); exit (1);

} for (col = 0; col < input size x ; ^{++}col ) grayrow [col ] = ; if (¬mf like) code = (min char &^{#}FF00) + min 2 byte; else {

if ((file number < (unicode ? 0 : 1)) ∨ (file number ≥ ^{#}100)) { fprintf (stderr , ␣ ␣ ); exit (1);

}

if (unicode) { offset = 0; code = file number ∗^{#}100;

}

else { offset = (file number − 1) ∗ 256 % nmb 2 bytes ; code = (min char &^{#}FF00) + min 2 byte + (file number − 1) ∗ 256/nmb 2 bytes ∗^{#}100;

}

while (offset^{−})

while (¬b2 codes [code^{++} &^{#}FF]) /∗ eliminate invalid b2 codes ∗/

; if (code > max char ) {

fprintf (stderr , ␣ ␣ );

exit (1); } } s mag x = mag x ∗ magstep x ∗ ; s mag y = mag y ∗ magstep y ∗ ; s slant = slant ∗ ;

}

This code is used in section 4.

29. All arrays of the pixelrow family contain gray values. While scaling with non-integer values a pixel of the input bitmap will normally not align with the pixel grid of the output bitmap (geometrically spoken). In this case we first compute the fractions of input pixel rows scaled vertically and add the corresponding gray values until a temporary row is produced. Then we repeat this procedure horizontally pixel by pixel and write the result into an output array. ⟨ Prototypes 11 ⟩ +≡

static void make pixel array (void); 30.

static void make pixel array (void) {

unsigned char ∗prP ; unsigned char ∗temp prP ; unsigned char ∗new prP ; long ∗grP ; register unsigned char ∗xP ; register unsigned char ∗nxP ; register int row , col ; int rows read = 0; register int need to read row = 1; long frac row to fill = ; long frac row left = s mag y ; int no code = ; prP = pixelrow ; temp prP = temp pixelrow ; new prP = new pixelrow ; grP = grayrow ; out char p = out char ; /∗ will be increased by write row ( ) ∗/

again:

if (b2 codes [code &^{#}FF]) /∗ a valid second byte? ∗/ {

if (pk files ) { bitmap = hbfGetBitmap(hbf , code); bP = bitmap; /∗ will be increased by read row ( ) ∗/ if (¬bitmap) empty char = ; else ⟨ Scale row by row 31 ⟩

} } else no code = ; if ((code &^{#}FF) ≡ max 2 byte) code += ^{#}FF − (max 2 byte − min 2 byte);

/∗ go to next plane ∗/ if (code ≥ max char ) {

end of file = ; return;

} code^{++}; if (no code) {

no code = ; goto again;

} } 31. ⟨ Scale row by row 31 ⟩ ≡

{

if (pk output size y ≡ input size y ) /∗ shortcut Y scaling if possible ∗/

temp prP = prP ; curr row = input size y − 1; /∗ only needed for rotated glyphs ∗/ for (row = 0; row < pk output size y ; ^{++}row ) {

⟨ Scale Y from pixelrow [ ] into temp pixelrow [ ] 32 ⟩

⟨ Scale X from temp pixelrow [ ] into new pixelrow [ ] and write it into out char [ ] 34 ⟩ }

}

This code is used in section 30.

32. ⟨ Scale Y from pixelrow [ ] into temp pixelrow [ ] 32 ⟩ ≡

if (pk output size y ≡ input size y ) /∗ shortcut Y scaling if possible ∗/

read row (prP ); else {

while (frac row left < frac row to fill ) {

if (need to read row )

if (rows read < input size y ) { read row (prP ); ++rows read ;

} for (col = 0, xP = prP ; col < input size x ; ^{++}col ,^{++}xP ) grP [col ] += frac row left ∗ (∗xP ); frac row to fill −= frac row left ; frac row left = s mag y ; need to read row = 1;

} ⟨ Produce a temporary row 33 ⟩

}

This code is used in section 31.

33. Now frac row left ≥ frac row to fill , so we can produce a row. ⟨ Produce a temporary row 33 ⟩ ≡

if (need to read row )

if (rows read < input size y ) { read row (prP ); ++rows read ; need to read row = 0;

} for (col = 0, xP = prP , nxP = temp prP ; col < input size x ; ^{++}col ,^{++}xP ,^{++}nxP ) {

register long g; g = grP [col ] + frac row to fill ∗ (∗xP ); g /= ; if (g > ) g = ; ∗nxP = g; grP [col ] = ;

} frac row left −= frac row to fill ; if (frac row left ≡ 0) {

frac row left = s mag y ; need to read row = 1;

} frac row to fill = ;

This code is used in section 32.

34. To implement the slant we move the starting point nxP to the right according to the corresponding y value. To simplify life only positive shift values are allowed.

We always append a white pixel to avoid artefacts at the end of the line produced by the last line. This rule sets the second condition that the slant must not be greater than 1—such a large slant would be unusable anyway for typesetting purposes. ⟨ Scale X from temp pixelrow [ ] into new pixelrow [ ] and write it into out char [ ] 34 ⟩ ≡

if (pk width ≡ input size x ∧ s slant ≡ 0) /∗ shortcut X scaling if possible ∗/

write row (temp prP ); else {

register long g = ; register long frac col to fill = ; register long frac col left ; register int need col = 0; nxP = new prP ; frac col left = (pk output size y − row ) ∗ s slant ; while (frac col left ≥ frac col to fill ) {

∗(nxP^{++}) = 0;

frac col left −= frac col to fill ; } if (frac col left > 0) frac col to fill −= frac col left ; for (col = 0, xP = temp prP ; col < input size x ; ^{++}col ,^{++}xP ) {

frac col left = s mag x ;

while (frac col left ≥ frac col to fill ) {

if (need col ) { ++nxP ; g = ;

}

g += frac col to fill ∗ (∗xP );

g /= ;

if (g > ) g = ; ∗nxP = g; frac col left −= frac col to fill ; frac col to fill = ; need col = 1;

}

if (frac col left > 0) {

if (need col ) { ++nxP ; g = ; need col = 0;

}

g += frac col left ∗ (∗xP ); frac col to fill −= frac col left ;

} } ⟨ Write out a row 35 ⟩

}

This code is used in section 31.

35. ⟨ Write out a row 35 ⟩ ≡

if (frac col to fill > 0) { −xP ; g += frac col to fill ∗ (∗xP );

}

if (¬need col ) { g /= ; if (g > ) g = ; ∗nxP = g;

}

∗(^{++}nxP ) = 0; /∗ append a blank pixel ∗/ write row (new prP );

This code is used in section 34.

36. read row ( ) reads a row from bitmap[ ] and converts it into a graymap row. If the rotation flag has been set, we get the proper column instead (note that in this case input size x already reflects the width of the rotated glyph). ⟨ Prototypes 11 ⟩ +≡

static #ifdef

inline #endif

void read row (unsigned char ∗); 37.

static #ifdef

inline #endif

void read row (unsigned char ∗pixelrow )

{ register int col , bitshift , offset ; register unsigned char ∗xP ; register unsigned char item = 0; if (rotation) {

bitshift = 7 − (curr row % 8); offset = (input size y + 7)/8; bP = bitmap + curr row /8; for (col = 0, xP = pixelrow ; col < input size x ; ^{++}col ,^{++}xP ) {

∗xP = ((∗bP ≫ bitshift ) & 1) ≡ 1 ? : 0; bP += offset ;

}

curr row^{−}; } else {

bitshift = −1;

for (col = 0, xP = pixelrow ; col < input size x ; ^{++}col ,^{++}xP ) {

if (bitshift ≡ −1) { item = ∗(bP^{++}); /∗ increase input bitmap pointer ∗/ bitshift = 7;

}

∗xP = ((item ≫ bitshift ) & 1) ≡ 1 ? : 0; −bitshift ;

} }

}

38. write row ( ) converts the graymap back into a bitmap using a simple threshold. ⟨ Global variables 2 ⟩ +≡

int threshold = 128;

39. ⟨ Prototypes 11 ⟩ +≡

static #ifdef

inline #endif

void write row (unsigned char ∗); 40.

static #ifdef

inline #endif

void write row (unsigned char ∗pixelrow )

{ register int col ; register unsigned char ∗xP ; for (col = 0, xP = pixelrow ; col < pk output size x ; ^{++}col ,^{++}xP )

∗(out char p^{++}) = (∗xP ≥ threshold ) ? 1 : 0; /∗ increase output bitmap pointer ∗/ }

41. Now comes the most interesting routine. The pixel array will be compressed in sequences of black and white pixels.

, , and indicate how many blank lines will be skipped. (x) means that the next x pixels will have the same color, then the color changes. (x) is the first black pixel in the next row.

An example: the pixel sequence 111100011001 [new row] 000111011110 will be output as 4 3 2 2 1 77 3 1 4 1.

Commands with an ending ‘n’ in its name indicate that the next n bytes should be read as the counter. Example: 26 means ‘skip the next 26 rows’.

For further details please refer to “ —the program”. #define (x) (x) /∗ 0 ≤ x ≤ 63 ∗/

#define  64
#define  65

#define 66 /∗ not used ∗/

#define  70
#define  71
#define  72
#define  73  /∗ not used ∗/
#define  (x) ((x) + 74)  /∗ 0 ≤ x ≤ 164 ∗/
#define  244  /∗ not used ∗/

⟨ Prototypes 11 ⟩ +≡ static void write coding (void); 42. The goto start instruction causes some compilers to complain about “Unreachable code …” or something similar.

static void write coding (void) {

register int count , skip; register unsigned char paint ; register int x, y; register unsigned char ∗cp; x = 0; y = 0; cp = out char + y ∗ pk output size x + x; count = skip = 0; paint = ; goto start ; while (y < pk output size y ) {

⟨ Search blank lines 43 ⟩ start : ⟨ Process rest of line 44 ⟩

y^{++}; }

} 43. ⟨ Search blank lines 43 ⟩ ≡

count = 0; x = 0; cp = out char + y ∗ pk output size x + x; while (x < pk output size x ) {

if (∗cp ≡ paint ) count^{++}; else {

if (skip ≡ 0) { if (count ≤ 164) fputc( (count ), out ); else {

fputc( , out ); if (count < 256) {

fputc( , out );

fputc(count , out ); } else {

fputc( , out );

fputc(count ≫ 8, out ); fputc(count &^{#}FF, out );

} }

} else {

if (skip ≡ 1) fputc( , out ); else {

if (skip < 256) { fputc( , out ); fputc(skip, out );

} else {

fputc( , out );

fputc(skip ≫ 8, out ); fputc(skip &^{#}FF, out );

} } skip = 0; if (count < 64) fputc( (count ), out ); else if (count < 256) {

fputc( , out ); fputc(count , out );

} else {

fputc( , out ); fputc(count ≫ 8, out ); fputc(count &^{#}FF, out );

} } count = 0; paint = ; break;

} x^{++}; cp^{++};

} if (x ≥ pk output size x ) {

skip^{++}; y^{++}; continue;

}

This code is used in section 42.

44. ⟨ Process rest of line 44 ⟩ ≡

while (x < pk output size x ) { if (∗cp ≡ paint ) count^{++}; else {

if (count < 64) fputc( (count ), out ); else if (count < 256) {

fputc( , out ); fputc(count , out );

}

else { fputc( , out ); fputc(count ≫ 8, out ); fputc(count &^{#}FF, out );

}

count = 1;

paint = − paint ; } x^{++}; cp^{++};

} if (paint ≡ ) {

if (count < 64) fputc( (count ), out ); else if (count < 256) {

fputc( , out );

fputc(count , out ); } else {

fputc( , out );

fputc(count ≫ 8, out );

fputc(count &^{#}FF, out ); } paint = ;

}

This code is used in section 42.

§45  hbf2gf (CJK Version 4.8.3)  THE FONT METRICS FILE 31

45. The font metrics file. This routine creates one file with the font properties. None of the TEX font dimensions are needed because you never will use CJK fonts directly, and intercharacter stretching is handled by the CJK macro . (Other packages may define similar commands.)

The name of the file will contain the running two digits in -like mode only.

It makes sense not to compute the check sum automatically for two reasons. Firstly, since TEX’s checksum algorithm is based on the character width, the number of valid characters, and the designsize, there is a much higher chance that two subfonts from different HBF fonts have the same check sum than it is for ordinary fonts, because all characters have the same width, usually 256 characters in a subfont, and very often the same design size. Secondly, and this is more important, we create just one file for all subfonts regardless of the real number of characters in a particular subfont.

To have an identification string in the file, we split it into single bytes and use the command repeatedly. ⟨ Prototypes 11 ⟩ +≡

static void write pl (void);

32  THE FONT METRICS FILE  hbf2gf (CJK Version 4.8.3) §46

46.

static void write pl (void) {

int i, pos ; char output file[ + 1]; long t, sc; char ∗s;

char tfm header [ ] =  ␣  ␣  ;
file number^{−};  /∗ for  -like mode ∗/

if (mf like) { if (unicode) sprintf (output file, , output name, file number ); else sprintf (output file, , output name, file number );

} else sprintf (output file, , output name); if (¬(out = fopen(output file, ))) {

fprintf (stderr , ␣ ␣ , output file);

exit (1); } if (¬quiet ) printf ( ␣ , output file); fprintf (out ,

␣

␣ , output name, file number , font encoding ); fprintf (out ,

␣ ␣
␣          ␣  ␣  ␣
␣     ␣      ␣   ␣         ␣   ␣

␣ ␣

␣␣␣      ␣ ␣

␣␣␣      ␣ ␣

␣␣␣        ␣ ␣
␣␣␣       ␣ ␣
␣␣␣        ␣ ␣

␣␣␣     ␣ ␣

␣␣␣          ␣ ␣

␣␣␣ , design size, checksum, slant ); s = tfm header ; i = strlen(s); t = ((long) i) ≪ 24; sc = 16; pos = 18; fprintf (out , ); while (i > 0) {

t |= ((long)(∗(unsigned char ∗) s^{++})) ≪ sc;

sc −= 8;

if (sc < 0) { fprintf (out , ␣ ␣ ␣ ␣ , pos , t); t = 0; sc = 24; pos^{++};

}

i^{−}; } if (t) fprintf (out , ␣ ␣ ␣ ␣ , pos , t); fprintf (out , ); for (i = 0; i < 256; i^{++}) {

fprintf (out ,

␣ ␣

␣␣␣       ␣ ␣
␣␣␣       ␣ ␣
␣␣␣       ␣ ␣
␣␣␣       ␣ ␣

␣␣␣ ,

i, tfm output size x + 2 ∗ tfm offset x , tfm output size y + tfm offset y , −tfm offset y ,

slant ∗ (tfm output size y + tfm offset y )); } fclose(out );

34  THE EXTENDED VIRTUAL FONT FILE FOR Ω  hbf2gf (CJK Version 4.8.3) §47

} 47. The extended virtual font file for Ω. The following is very similar to write pl ( ); we simply map the glyphs of the subfonts back to the original encoding positions. ⟨ Prototypes 11 ⟩ +≡

static void write ovp(void);

§48  hbf2gf (CJK Version 4.8.3)  THE EXTENDED VIRTUAL FONT FILE FOR Ω 35

48.

static void write ovp(void) {

int c, i, nmb subfonts , remainder , count , pos ; char output file[ + 1]; long t, sc; char ∗s; char ofm header [ ] = ␣ ␣ ; nmb subfonts = ((max char − (min char &^{#}FF00))/256 ∗ nmb 2 bytes )/256 + 1; remainder = ((max char − (min char &^{#}FF00))/256 ∗ nmb 2 bytes ) % 256;

/∗ correction for the last incomplete second byte range ∗/ for (count = 0; count < (max char &^{#}FF); count^{++})

if (b2 codes [count ]) remainder^{++}; if (remainder ≥ 256) nmb subfonts^{++}; sprintf (output file, , output name); if (¬(out = fopen(output file, ))) {

fprintf (stderr , ␣ ␣ , output file); exit (1);

} if (¬quiet ) printf ( ␣ , output file); fprintf (out ,

␣     ␣        ␣    ␣       ␣   ␣
␣ ␣
␣          ␣  ␣  ␣
␣     ␣      ␣   ␣         ␣   ␣

␣ ␣

␣␣␣      ␣ ␣

␣␣␣      ␣ ␣

␣␣␣        ␣ ␣
␣␣␣       ␣ ␣
␣␣␣        ␣ ␣

␣␣␣     ␣ ␣

␣␣␣          ␣ ␣

␣␣␣ , design size, checksum, slant ); s = ofm header ; i = strlen(s); t = ((long) i) ≪ 24; sc = 16; pos = 18; fprintf (out , ); while (i > 0) {

t |= ((long)(∗(unsigned char ∗) s^{++})) ≪ sc;

sc −= 8;

if (sc < 0) { fprintf (out , ␣ ␣ ␣ ␣ , pos , t); t = 0; sc = 24; pos^{++};

}

i^{−}; } if (t) fprintf (out , ␣ ␣ ␣ ␣ , pos , t); fprintf (out , ); for (i = 0; i < nmb subfonts ; i^{++}) {

fprintf (out ,

␣ ␣

␣␣␣         ␣
␣␣␣            ␣  ␣
␣␣␣       ␣ ␣
␣␣␣          ␣ ␣

␣␣␣ , i, output name, i + 1, checksum, design size); } for (c = min char , i = 0, count = 0; c ≤ max char ; c^{++}) {

if (b2 codes [c &^{#}FF] ≡ ) { fprintf (out ,

␣ ␣

␣␣␣       ␣ ␣
␣␣␣       ␣ ␣
␣␣␣       ␣ ␣
␣␣␣       ␣ ␣

␣␣␣

␣␣␣␣␣␣           ␣ ␣
␣␣␣␣␣␣        ␣ ␣

␣␣␣␣␣␣
␣␣␣ ,

c, tfm output size x + 2 ∗ tfm offset x , tfm output size y + tfm offset y , −tfm offset y ,

slant ∗ (tfm output size y + tfm offset y ), i, count ); count^{++}; if (count ≡ 256) {

count = 0; i^{++};

} } else continue;

} fclose(out );

§49  hbf2gf (CJK Version 4.8.3)  THE JOB FILE 37

} 49. The job file. This routine is the most system specific one. If your operating system needs a different outline, make appropriate changes here.

You have to call this batch file after has finished (if not in -like mode). It will transform the files into files and delete the now unnecessary files, then transform the file into a file and copy it nmb files times. The name of the job file is output name. #define 8 /∗ the maximal length of a file extension ∗/

#define
#define
#define

⟨ Global variables 2 ⟩ +≡ char job extension[ + 1]; char rm command [ + 1]; char cp command [ + 1]; char pk directory [ + 1]; char tfm directory [ + 1]; int ofm file = ;

50. ⟨ Prototypes 11 ⟩ +≡

static void write job(void);

38  THE JOB FILE  hbf2gf (CJK Version 4.8.3) §51

51.

static void write job(void) {

FILE ∗out ; int i, j; char buffer [ + 1]; strcpy (buffer , output name); strcat (buffer , job extension); if (¬(out = fopen(buffer , ))) {

fprintf (stderr , ␣ ␣ , buffer ); exit (1);

} if (¬quiet ) printf ( ␣ , buffer ); if (pk files ) {

if (unicode) {

for (i = (min char ≫ 8), j = 0; j < nmb files ; i^{++}, j^{++}) fprintf (out ,

    ␣         ␣

    ␣  ,

, output name, i,

pk directory , output name, i, long extension ? (int)(dpi x ∗ magstep x + 0.5) : 0, rm command , output name, i);

} else {

for (i = 1; i ≤ nmb files ; i^{++}) fprintf (out ,

    ␣         ␣

    ␣  ,

, output name, i,

pk directory , output name, i, long extension ? (int)(dpi x ∗ magstep x + 0.5) : 0, rm command , output name, i);

} } if (tfm files ) {

fprintf (out ,

␣     ␣
␣

, , output name, output name, rm command , output name); if (unicode) {

for (i = (min char ≫ 8), j = 0; j < nmb files ; i^{++}, j^{++}) fprintf (out ,

    ␣      ␣  ,

cp command , output name, tfm directory , output name, i); } else {

for (i = 1; i ≤ nmb files ; i^{++}) fprintf (out ,

    ␣      ␣  ,

cp command , output name, tfm directory , output name, i); } fprintf (out ,

␣  ,

rm command , output name); } if (ofm file) {

fprintf (out ,

␣      ␣      ␣

␣

, , output name, output name, output name, rm command , output name);

} fclose(out );

40  THE CONFIGURATION FILE  hbf2gf (CJK Version 4.8.3) §52

} 52. The configuration file. Here is a list with all necessary keywords (and parameters):

the HBF header file name of the input font(s).
the name stem of the output files.

Should be equal to the name of the configuration file in most cases. A running two digit decimal number starting with will be appended. (For Unicode fonts see the keyword below.)

And now all optional keywords:

increases the character width.

Will be applied on both sides; default is the value given in the HBF header ( ) scaled to designsize (in pixels).

shifts all characters up or down;

default is the value given in the HBF header ( ) scaled to designsize (in pixels).

the design size (in points) of the font.

and refer to this size. Default is 10.0

This command is obsolete now and will be ignored.
the slant of the font (given as Δx/Δy).

Only values in the range 0 ≤ slant ≤ 1 are allowed. Default is 0.0

if set to ‘yes’. the glyphs are rotated 90 degrees counter-clockwise.

The default offsets as given in the HBF header will be ignored (and set to 0). Default is ‘no’.

scaling values of the characters to reach design size.

If only one magnification is given, x and y values are assumed to be equal. Default is = = 1.0

A value between 1 and 254 defining a threshold for converting the internal

graymap into the output bitmap; lower values cut more pixels. Default value is 128.

a comment describing the font;

default is none.

the number of the fonts.

Default value is −1 for creating all fonts.

if ‘yes’, a two digit hexadecimal number will be used as a running number,

starting with the value of the first byte of the first code range. Default is ‘no’.

the minimum of the encoding range.

Specify this value if it is not identical to the lowest code value in the HBF file (to which it defaults).

the horizontal and vertical resolution (in dpi) of the printer.

If only one resolution is given, x and y values are assumed to be equal. Default is 300.

a checksum to identify the files with the appropriate  files.

§52  hbf2gf (CJK Version 4.8.3)  THE CONFIGURATION FILE 41

The default of this 32 bit unsigned integer is 0.

a comment describing the coding scheme;

default is none.

the destination directory of the files;

default: none.

Attention! The batch file will not check whether this directory exists.

the destination directory of the  files;

default: none.

Attention! The batch file will not check whether this directory exists.

whether to create files or not;

default is ‘yes’.

whether to create  files or not;

default is ‘yes’.

whether to create an and an file or not;

default is ‘no’.

if ‘yes’, files will include the resolution in the extension

(e.g. ).

This affects the batch file only (default is ‘yes’).

this shell command removes files;

default: ‘rm’.

this shell command copies files;

default: ‘cp’.

the extension of the batch file which calls  and

to convert the and the files into and files;

default is none.

The searching algorithm (for the keywords) of is case insensitive; it makes no difference whether you write for example or . The keywords must start a line (be in the first column), and the corresponding parameters must be on the same line with the keyword and separated by at least one space or tabulator stop. Lines starting not with a keyword are ignored.

Key values are case sensitive (except and ). The default system dependent values are for UNIX-like operating systems; if you use for example

DOS, you must write

Both the values pk output size x and pk output size y must not exceed ; and are related to the design size (and not to the input size).

In -like mode, one file and one file will be computed (depending on the command line options and ), taking x resolution and y scale from the command line. will always be set to 1; no job file will be created.

53.

#define  50
#define  50

⟨ Global variables 2 ⟩ +≡ char Buffer [ + 1]; 54. ⟨ Prototypes 11 ⟩ +≡

static void read config (void);

55. If config file isn’t found in -like mode we assume that the font isn’t a HBF font at all. static void read config (void) {

HBF BBOX ∗boxp; char ∗real config file; ⟨ Handle extension 56 ⟩ real config file = TeX search cfg file(config file); if (¬real config file) {

if (mf like) { if (¬quiet ) printf ( ␣ ␣ , config file); exit (2);

}

else { fprintf (stderr , ␣ ␣ , config file); exit (1);

} } if (¬(config = fopen(real config file, ))) {

if (¬testing ) { fprintf (stderr , ␣ ␣ , config file); exit (1);

}

else /∗ We reach this point only if no searching library is used ∗/ {

if (¬quiet ) fprintf (stderr , ␣ ␣ ␣ ␣ , config file); exit (2);

} } if (testing ) {

if (¬quiet ) printf ( , real config file);

exit (0); } ⟨ Necessary parameters 57 ⟩ ⟨ Optional parameters 59 ⟩ ⟨ Get code range 61 ⟩ ⟨ Get sub code range 63 ⟩ fclose(config );

} 56. Here we check whether we have to add an extension. ⟨ Handle extension 56 ⟩ ≡

{ int i, lastext = −1; for (i = 0; config file[i]; i^{++})

if (config file[i] ≡ ) lastext = i;

else if (config file[i] ≡ ∨ config file[i] ≡ ∨ config file[i] ≡ ) lastext = −1; if (lastext ≡ −1) strcat (config file, );

}

This code is used in section 55.

57. ⟨ Necessary parameters 57 ⟩ ≡

{ char hbf header [ + 1]; char ∗real hbf header ; if (¬fsearch( )) config error ( ); else strcpy (hbf header , Buffer ); real hbf header = TeX search hbf file(hbf header ); if (¬real hbf header ) {

fprintf (stderr , ␣ ␣ , hbf header );

exit (1); } hbfDebug = 1;

/∗ we activate error messages of the HBF API while scanning the HBF header file ∗/ if (¬(hbf = hbfOpen(real hbf header ))) exit (1); hbfDebug = 0; boxp = hbfBitmapBBox (hbf ); input size x = boxp hbf height ; /∗ will be checked later for rotation ∗/ input size y = boxp hbf width; font encoding = hbfProperty (hbf , ); if (¬fsearch( )) config error ( ); else strcpy (output name, Buffer );

}

This code is used in section 55.

58. ⟨ Global variables 2 ⟩ +≡

int offset x ; int offset y ; HBF CHAR user min char ; int have min char = ; 59. ⟨ Optional parameters 59 ⟩ ≡

{ if (fsearch( )) nmb files = atoi (Buffer ); if (fsearch( ))

if (Buffer [0] ≡ ∨ Buffer [0] ≡ ) unicode = ; if (fsearch( )) {

user min char = strtoul (Buffer , (char ∗∗) Λ, 0);

have min char = ; } if (¬mf like) {

if (fsearch( ))

if (Buffer [0] ≡ ∨ Buffer [0] ≡ ) pk files = ; if (fsearch( ))

if (Buffer [0] ≡ ∨ Buffer [0] ≡ ) tfm files = ; if (fsearch( ))

if (Buffer [0] ≡ ∨ Buffer [0] ≡ ) ofm file = ; if (fsearch( ))

if (Buffer [0] ≡ ∨ Buffer [0] ≡ ) long extension = ; } if (fsearch( )) slant = atof (Buffer ); if (slant < 0.0 ∨ slant > 1.0) {

fprintf (stderr , ␣ );

exit (1); } if (fsearch( ))

if (Buffer [0] ≡ ∨ Buffer [0] ≡ ) rotation = ; if (fsearch( )) mag x = atof (Buffer ); if (fsearch( )) mag y = atof (Buffer ); if (¬mag x ∧ ¬mag y ) {

mag x = 1.0;

mag y = 1.0; } if (mag x ∧ ¬mag y ) mag y = mag x ; if (mag y ∧ ¬mag x ) mag x = mag y ; if (mag x ≤ 0.0) {

fprintf (stderr , ␣ ␣ ); exit (1);

} if (mag y ≤ 0.0) {

fprintf (stderr , ␣ ␣ ); exit (1);

} if (fsearch( )) dpi x = atoi (Buffer ); if (fsearch( )) dpi y = atoi (Buffer ); if (¬dpi x ∧ ¬dpi y ) {

dpi x = 300;

dpi y = 300; } if (dpi x ∧ ¬dpi y ) dpi y = dpi x ; if (dpi y ∧ ¬dpi x ) dpi x = dpi y ; if (dpi x ≤ ) {

fprintf (stderr , ␣ ␣ ␣ ); exit (1);

} if (dpi y ≤ ) {

fprintf (stderr , ␣ ␣ ␣ ); exit (1);

} if (fsearch( )) design size = atof (Buffer ); if (fsearch( )) offset x = atoi (Buffer ); else offset x = rotation ? 0 : (boxp hbf xDisplacement ∗ mag x + 0.5); if (fsearch( )) offset y = atoi (Buffer ); else offset y = rotation ? 0 : (boxp hbf yDisplacement ∗ mag y + 0.5); if (¬fsearch( )) comment [0] = ; else strcpy (comment , Buffer ); if (fsearch( )) threshold = atoi (Buffer ); if (threshold ≤ 0 ∨ threshold ≥ 255) {

fprintf (stderr , ␣ );

exit (1); } if (¬fsearch( )) checksum = 0; else checksum = strtoul (Buffer , (char ∗∗) Λ, 0); if (¬fsearch( )) coding [0] = ; else strcpy (coding , Buffer ); if (¬fsearch( )) pk directory [0] = ; else strcpy (pk directory , Buffer ); if (¬fsearch( )) tfm directory [0] = ; else strcpy (tfm directory , Buffer ); if (fsearch( )) strcpy (rm command , Buffer ); else strcpy (rm command , ); if (fsearch( )) strcpy (cp command , Buffer ); else strcpy (cp command , ); if (¬fsearch( )) job extension[0] = ; else {

strncpy (job extension, Buffer , );

job extension[ ] = ; }

}

This code is used in section 55.

60. The function hbfGetCodeRange( ) is an extension to the HBF API.

Successive calls return the code ranges in ascending order; we only need the extrema of the whole code range.

In case min char has been supplied in the configuration file, we use that value instead. ⟨ Global variables 2 ⟩ +≡

HBF CHAR min char , max char ; 61. ⟨ Get code range 61 ⟩ ≡

{ const void ∗cp; HBF CHAR dummy ; cp = hbfGetCodeRange(hbf , Λ, &min char , &max char ); for ( ; cp ≠ Λ; cp = hbfGetCodeRange(hbf , cp, &dummy , &max char )) ; if (have min char ) min char = user min char ;

}

This code is used in section 55.

62. The function hbfGetByte2Range( ) is an extension to the HBF API.

Successive calls return the byte 2 ranges in ascending order. We raise in the array b2 codes [ ] for all characters in subcode ranges.

#define  1

⟨ Global variables 2 ⟩ +≡ char b2 codes [256]; unsigned char min 2 byte, max 2 byte; int nmb 2 bytes = 0;

63. ⟨ Get sub code range 63 ⟩ ≡

{ const void ∗b2r ; unsigned char dummy ; int i; for (i = 0; i < 256; i^{++}) b2 codes [i] = 0; b2r = hbfGetByte2Range(hbf , Λ, &min 2 byte, &max 2 byte); dummy = min 2 byte; for ( ; b2r ≠ Λ; b2r = hbfGetByte2Range(hbf , b2r , &dummy , &max 2 byte)) {

for (i = dummy ; i ≤ max 2 byte; i^{++}) b2 codes [i] = ; } for (i = 0; i < 256; i^{++}) /∗ compute the number of valid b2 codes ∗/

if (b2 codes [i] ≡ ) nmb 2 bytes^{++}; }

This code is used in section 55.

64. This search routine is case insignificant. Each keyword must start a line; the function checks whether the character before the keyword is a newline character ( ). It also checks the presence of a parameter and fills Buffer if existent. fsearch( ) returns 1 on success. ⟨ Prototypes 11 ⟩ +≡

static int fsearch(const char ∗); 65.

static int fsearch(const char ∗search string ) {

char ∗P , p; const char ∗Q; char temp buffer [ + 1]; char env name[ + 1]; char ∗env p; char ∗env value; char ∗Buf p; int Ch, ch, old ch = ; int count = ; rewind (config ); /∗ we start at offset 0 ∗/ do {

Q = search string ;

p = tolower ((unsigned char) ∗Q);

Ch = fgetc(config );

ch = tolower (Ch);

while (¬(ch ≡ p ∧ old ch ≡ ) ∧ Ch ≠ )

/∗ search first character of search string ; must be the character before ∗/ {

old ch = ch;

Ch = fgetc(config ); ch = tolower (Ch);

}

for ( ; ; ) {

if (∗(^{++}Q) ≡ )

if ((Ch = fgetc(config )) ≡ ␣ ∨ Ch ≡ )

/∗ there must be a space or a tab stop after the keyword ∗/ goto success ; Ch = fgetc(config ); if (tolower (Ch) ≠ tolower ((unsigned char) ∗Q)) break;

} } while (Ch ≠ ); return 0;

success : P = temp buffer ;

while ((Ch = fgetc(config )) ≡ ␣ ∨ Ch ≡ ) /∗ remove leading blanks and tabs ∗/

; while (Ch ≠ ∧ ^{−}count > 0 ∧ Ch ≠ ) /∗ fill Buffer ∗/ {

∗P^{++} = Ch;

Ch = fgetc(config ); } ∗P = ; if (∗temp buffer ) ⟨ Check for environment variables 66 ⟩ else ∗Buffer = ; return (∗Buffer ) ? 1 : 0; /∗ is there something in the buffer? ∗/

} 66. To make the configuration file more flexible we allow environment variables in the arguments. We scan the parameter stored in temp buffer whether it contains a ‘ ’ character. If yes, the following code fragment tries to get an environment variable name whose value will be then fetched with getenv ( ). An environment variable name recognized by must start with a letter or underscore; the other characters may be alphanumeric or an underscore. You can surround the environment variable name with braces to indicate where the name ends, e.g. . The interpolated configuration parameter will be truncated to characters. If you want to have ‘ ’ you must write ‘ ’.

Note that you should avoid to use such environment variables for specifying the location of the configuration file in case you have support for a file searching library like kpathsea. Its primary aim is to specify the target directories for the and the keywords. ⟨ Check for environment variables 66 ⟩ ≡

{ P = temp buffer ; Buf p = Buffer ; count = − 1; while (∗P ∧ count > 0) {

env p = env name; if (∗P ≡ ) {

P^{++}; if (∗P ≡ ) {

∗(Buf p^{++}) = ∗(P^{++});

count^{−};

continue; } while (∗P ≡ ) P^{++}; if (¬(isalpha((unsigned char) ∗P) ∨ ∗P ≡ )) {

fprintf (stderr ,

  ␣           ␣        ␣    ␣  ␣             ␣  );

exit (1); } ∗(env p^{++}) = ∗(P^{++}); while (∗P) {

if (isalnum((unsigned char) ∗P) ∨ ∗P ≡ ) ∗(env p^{++}) = ∗(P^{++}); else {

while (∗P ≡ ) P^{++};

∗env p = ;

break; }

} env value = getenv (env name); if (env value) /∗ append the environment value to Buffer ∗/ {

while (∗env value ∧ count > 0) { ∗(Buf p^{++}) = ∗(env value^{++}); count^{−};

} }

} else {

∗(Buf p^{++}) = ∗(P^{++}); count^{−};

} } ∗Buf p = ;

}

This code is used in section 65.

67. If an error occurs, config error ( ) will leave the program with an error message. ⟨ Prototypes 11 ⟩ +≡

static void config error (const char ∗);

68.

static void config error (const char ∗message) {

fprintf (stderr , ␣ ␣ ␣ ␣ ␣ ␣ , message); exit (1);

50  FILE SEARCHING  hbf2gf (CJK Version 4.8.3) §69

} 69. File searching.

We support three searching engines: emtexdir, kpathsea, and MiKTeX (which is a Win32 port of kpathsea). For emtexdir, define while compiling. For kpathsea, define . For MikTeX, define . If none of these macros is defined, a simple fopen( ) will be used instead. ⟨ Include files 10 ⟩ +≡ #if defined ( ) #include #elif defined ( ) #include #elif defined ( ) #include #endif

70. ⟨ Global variables 2 ⟩ +≡ #if defined ( )

char emtex version string [ ] = ; #elif ¬defined ( )

char no version string [ ] = ␣ ␣ ; #endif

71. ⟨ Prototypes 11 ⟩ +≡

static const char ∗TeX search version(void);

72.

static const char ∗TeX search version(void)

{ #if defined ( )

return kpathsea version string ; #elif defined ( )

return emtex version string ; #elif defined ( )

char buf [200];

strcpy (buf , ␣ );

miktex get miktex version string ex (buf + 7, sizeof (buf ) − 7); return buf ;

#else

return no version string ; #endif

}

73. ⟨ Global variables 2 ⟩ +≡ #ifdef

§74  hbf2gf (CJK Version 4.8.3)  FILE SEARCHING 51

struct emtex dir cfg path, hbf path; #endif 74. ⟨ Prototypes 11 ⟩ +≡ #ifdef

extern int setup list (struct emtex dir ∗, char ∗, const char ∗, unsigned); static int dir setup(struct emtex dir ∗, const char ∗, const char ∗, unsigned); static char ∗file find (char ∗, struct emtex dir ∗);

#endif

75. We slightly modify emtex dir setup( ) (from the file ) to output a warning in case the environment variable env isn’t set properly. #ifdef

static int dir setup(ed , env , dir , flags )

struct emtex dir ∗ed ; const char ∗env ; const char ∗dir ; unsigned flags ;

{ const char ∗val ; char path[260]; ed alloc = 0; ed used = 0; ed list = Λ; if (env ≠ Λ ∧ (val = getenv (env )) ≠ Λ) return setup list (ed , path, val , flags ); else fprintf (stderr , ␣ ␣ ␣ ␣ ␣ ␣ ␣ , env ); return ;

} #endif

76. ⟨ Global variables 2 ⟩ +≡ #ifdef

char name buffer [ + 1]; #endif

77. #ifdef

static char ∗file find (name, list )

char ∗name;

struct emtex dir ∗list ; {

if (emtex dir find (name buffer , sizeof (name buffer ), list , name, )) return name buffer ; return Λ;

} #endif

78. For emtexdir we use the environment variables  and  for configuration resp. HBF

header files. ⟨ Initialize TEX file searching 78 ⟩ ≡ #if defined ( )

kpse set program name(argv [0], );

kpse init prog ( , 300, , ); #elif defined ( )

if (¬dir setup(&cfg path,  , Λ,  )) {
fprintf (stderr ,  ␣     ␣       ␣    ␣   ␣             ␣  );

exit (1); }

if (¬dir setup(&hbf path,  , Λ,  )) {
fprintf (stderr ,  ␣     ␣       ␣    ␣   ␣   ␣      ␣  );

exit (1); }

#endif

This code is used in section 4.

79. Finally, here are the searching routines. A special format in the kpathsea library for fonts which are neither PostScript nor TrueType ( ) is available with version 3.3 and newer. For older versions we use the path for PostScript fonts ( ) to find HBF files. Configuration files are searched in the path specified within for old kpathsea versions, and within for new versions. ⟨ Prototypes 11 ⟩ +≡

static char ∗TeX search cfg file(char ∗);

static char ∗TeX search hbf file(char ∗); 80. #if defined ( )

static char ∗TeX search cfg file(char ∗name) {

return kpse find file(name, kpse program text format , ); } static char ∗TeX search hbf file(char ∗name) {

return kpse find file(name, kpse miscfonts format , ); }

#elif defined ( )

static char ∗TeX search cfg file(char ∗name) {

return file find (name, &cfg path); } static char ∗TeX search hbf file(char ∗name) {

return file find (name, &hbf path); }

#elif defined ( )

static char ∗TeX search cfg file(char ∗name) {

char result [ ];

if (¬miktex find input file( , ∗name, result )) return 0; return strdup(result );

} static char ∗TeX search hbf file(char ∗name) {

char result [ ];

if (¬miktex find miscfont file(∗name, result )) return 0; return strdup(result );

} #else

static char ∗TeX search cfg file(char ∗name) {

return name; } static char ∗TeX search hbf file(char ∗name) {

return name; }

#endif

54  AN EXAMPLE  hbf2gf (CJK Version 4.8.3) §81

81. An example. This is the example configuration file (for use with DOS or OS/2 and the emtexdir searching engine):

If you say e.g. on your DOS prompt (or in your file), then the interpolated value of the

keyword is . The HBF header file will be searched in the path specified by the environment variable.

The call creates the files

, , …, , , and After calling you will find the files in the directory and the files in the

directory; all files and will be deleted.

The call creates two files:

and using the configuration file . The file would be named if the flag

had not been used.

§81  hbf2gf (CJK Version 4.8.3)  AN EXAMPLE 55

It is possible to convert bitmap fonts to files almost automatically. The HBF header file already has the entry which defines vertical and horizontal offsets (in pixels), but these values are not in all cases optimal. If you omit and in the configuration file, the third and fourth parameter of is used, scaled to design size (to say it in other words: and will always apply to the design size to be synchronous with the files).

Don’t confuse scaling and magnification: Scaling here means that you choose a (arbitrary) design size

and compute scaling values (  and  ) which scales the bitmap to this particular design size
at a certain (arbitrarily chosen) resolution (  and  ). Magnification means that the scaled

bitmap will be then magnified to a certain target size while still using the font parameters (i.e., the file) of the design size.

In the sample, you have a 24 × 24 bitmap font which will be scaled to 12 pt having a resolution of 300 dpi:

1 pt are 300/72.27 = 4.1511 pixel; 12 pt are 4.1511 ∗ 12 = 49.813 pixel; thus the theoretical scaling value is 49.813/24 = 2.076.

But especially for small sizes, this may not be the best value if the font should harmonize with, say, Knuth’s Computer Modern fonts. I recommend to compute, say, 5 fonts, then check the CJK font with different TEX fonts to see whether the offsets and/or the scaling value is good. The greater the design size the finer you can control the offsets—as an example you could use a design size of 30 pt (nevertheless there is a compile-time constant which limits the maximal character size; default is 255 pixels).

If you have found optimal offsets, you can produce many different magnifications of the CJK font using the same set of files analogous to ordinary TEX fonts; as a simplification, we assume that files with a resolution of 300 dpi and a design size of 10 pt have the extension ‘ ’ (respectively come into a ‘ ’ subdirectory)—this is the reason why in the above example for the 12 pt design size a ‘ ’ target directory has been used. Now we can use the following formula:

needed dpi = your horizontal resolution ∗ \frac{your target size}{10.0}

Example: assuming that your printer has a resolution of 300 × 400 dpi, and you want 14.4 pt:

300 ∗ \frac{14.4}{10.0} = 432

The vertical scaling value is 400/300 = 1.3333. Use these values now to call  in  -like

mode:

56  INDEX  hbf2gf (CJK Version 4.8.3) §82

82. Index.

: 36, 37, 39, 40.

inline : 36, 37, 39, 40. : 80. : \underline{19}, 23. : \underline{19}, 21. again: \underline{30}. alloc: 75. argc: \underline{4}, 7, 8. argv : \underline{4}, 7, 8, 78. atof : 8, 59. atoi : 8, 59. banner : \underline{1}, 4, 5. bitmap: \underline{27}, 30, 36, 37. bitshift : \underline{37}. : \underline{27}, 43, 44. : \underline{18}. : \underline{18}. boxp: \underline{55}, 57, 59. bP : \underline{27}, 30, 37. buf : \underline{72}. Buf p: \underline{65}, 66. buffer : \underline{51}. Buffer : \underline{53}, 57, 59, 64, 65, 66. b2 codes : 28, 30, 48, \underline{62}, 63. b2r : \underline{63}. c: \underline{48}. cfg path: \underline{73}, 78, 80. ch: \underline{65}. Ch: \underline{65}. char adr : \underline{15}, 17, 23. char adr p: \underline{15}, 17, 18, 23. : \underline{23}. : \underline{23}. checksum: \underline{19}, 23, 46, 48, 59. code: \underline{27}, 28, 30. coding : \underline{19}, 22, 59. col : \underline{28}, \underline{30}, 32, 33, 34, \underline{37}, \underline{40}. comment : \underline{19}, 22, 59. config : \underline{2}, 55, 65. config error : 57, \underline{67}, \underline{68}. config file: \underline{2}, 4, 55, 56. count : \underline{42}, 43, 44, \underline{48}, \underline{65}, 66. cp: \underline{42}, 43, 44, \underline{61}. cp command : \underline{49}, 51, 59. curr row : \underline{27}, 31, 37. design size: \underline{15}, 21, 28, 46, 48, 59. designsize: \underline{21}, 23. dir : \underline{75}. dir setup: \underline{74}, \underline{75}, 78. dot count : \underline{15}, 17, 18. dpi x : \underline{19}, 21, 28, 51, 59. dpi y : \underline{19}, 21, 28, 59. dummy : \underline{61}, \underline{63}. ed : \underline{75}. : 77. : 78. empty char : \underline{15}, 18, 30. emtex dir: 73, 74, 75, 77. emtex dir find : 77. emtex dir setup: 75. emtex version string : \underline{70}, 72. end of file: \underline{2}, 9, 17, 18, 27, 30. env : \underline{75}. env name: \underline{65}, 66. env p: \underline{65}, 66. env value: \underline{65}, 66. : \underline{18}. : 27, 65. exit : 4, 5, 6, 7, 8, 12, 28, 46, 48, 51, 55, 57,

59, 66, 68, 78. : \underline{49}, 59. f: \underline{26}. : \underline{2}, 7, 18, 30, 49, 58, 59. fclose: 12, 46, 48, 51, 55. fflush: 18. fgetc: 65. file find : \underline{74}, \underline{77}, 80. file name: 4. : \underline{2}, 4, 12, 46, 48, 51, 76. file number : \underline{2}, 8, 9, 12, 28, 46. flags : \underline{75}. font encoding : \underline{15}, 46, 57. fopen: 12, 46, 48, 51, 55, 69. fprintf : 7, 8, 12, 28, 46, 48, 51, 55, 57, 59,

66, 68, 75, 78. fputc: 14, 18, 22, 23, 24, 26, 43, 44. fputl : 18, 23, 24, \underline{25}, \underline{26}. fputs : 14, 22. frac col left : \underline{34}. frac col to fill : \underline{34}, 35. frac row left : \underline{30}, 32, 33. frac row to fill : \underline{30}, 32, 33. fsearch: 57, 59, \underline{64}, \underline{65}. ftell : 18, 22, 23, 24. g: \underline{33}, \underline{34}. getenv : 66, 75. : \underline{13}, 14, 24. : \underline{49}, 51. grayrow : \underline{27}, 28, 30. grP : \underline{30}, 32, 33. : \underline{27}, 28, 33, 34. : 10.

§82  hbf2gf (CJK Version 4.8.3)  INDEX 57

: 69, 70, 72, 73, 74, 75, 76,

77, 78, 80. : 69, 72, 78, 80. : 69, 70, 72, 80. have min char : \underline{58}, 59, 61. HBF: 2. hbf : \underline{2}, 4, 30, 57, 61, 63. HBF BBOX: 55. HBF CHAR: 27, 58, 60, 61. hbf header : \underline{57}. hbf height : 57. hbf path: \underline{73}, 78, 80. hbf width: 57. hbf xDisplacement : 59. hbf yDisplacement : 59. hbfBitmapBBox : 57. hbfClose: 4. hbfDebug : 57. hbfGetBitmap: 30. hbfGetByte2Range: 62, 63. hbfGetCodeRange: 60, 61. hbfOpen: 57. hbfProperty : 57. headertstring : \underline{13}, 14. i: \underline{21}, \underline{46}, \underline{48}, \underline{51}, \underline{56}, \underline{63}. input size x : \underline{15}, 28, 32, 33, 34, 36, 37, 57. input size y : \underline{15}, 28, 31, 32, 33, 37, 57. isalnum: 66. isalpha: 66. item: \underline{37}. j: \underline{9}, \underline{51}. job extension: \underline{49}, 51, 59. kpathsea version string : 72. kpse find file: 80. kpse init prog : 78. kpse miscfonts format : 80. kpse program text format : 80. kpse set program name: 78. l: \underline{4}. last char : \underline{15}, 17, 18, 23. lastext : \underline{56}. list : 75, \underline{77}. localtime: 14. long extension: \underline{2}, 7, 12, 51, 59. mag x : \underline{15}, 28, 59. mag y : \underline{15}, 28, 59. magstep x : \underline{15}, 21, 28, 51. magstep y : \underline{15}, 21, 28. main: \underline{4}. make pixel array : 18, 27, \underline{29}, \underline{30}. max char : 28, 30, 48, \underline{60}, 61. : 23, \underline{27}, 28, 52, 81. max numb: \underline{9}. max 2 byte: 30, \underline{62}, 63. message: \underline{68}. mf like: \underline{2}, 4, 9, 12, 28, 46, 55, 59. miktex find input file: 80. miktex find miscfont file: 80. miktex get miktex version string ex : 72. min char : 9, 28, 48, 51, \underline{60}, 61. min 2 byte: 28, 30, \underline{62}, 63. : 2. name: \underline{77}, \underline{80}. name buffer : \underline{76}, 77. need col : \underline{34}, 35. need to read row : \underline{30}, 32, 33. new pixelrow : \underline{27}, 30. new prP : \underline{30}, 34, 35. : \underline{41}, 43. nmb files : \underline{2}, 3, 9, 49, 51, 59. nmb subfonts : \underline{48}. nmb 2 bytes : 28, 48, \underline{62}, 63. no code: \underline{30}. no version string : \underline{70}, 72. : \underline{41}. num: \underline{26}. nxP : \underline{30}, 33, 34, 35. offset : \underline{28}, \underline{37}. offset x : 28, \underline{58}, 59. offset y : 28, \underline{58}, 59. ofm file: 4, \underline{49}, 51, 59. ofm header : \underline{48}. old ch: \underline{65}. out : \underline{2}, 12, 14, 18, 22, 23, 24, 43, 44, 46, 48, \underline{51}. out char : \underline{27}, 30, 42, 43. out char p: \underline{27}, 30, 40. out s : \underline{14}. output file: \underline{12}, \underline{46}, \underline{48}. output name: \underline{2}, 12, 46, 48, 49, 51, 57. : \underline{49}, 51. P: \underline{65}. p: \underline{4}, \underline{65}. paint : \underline{42}, 43, 44. : \underline{41}, 43, 44. : \underline{41}, 43, 44. : \underline{41}, 43, 44. : \underline{41}. path: \underline{75}. : \underline{27}, 33, 34, 35, 37. pixelrow : \underline{27}, 30, \underline{37}, \underline{40}. pk directory : \underline{49}, 51, 59. pk dx : 19, \underline{21}, 23. pk files : \underline{2}, 7, 12, 18, 30, 51, 59. pk offset x : \underline{15}, 18, 21, 28. pk offset y : \underline{15}, 18, 21, 28. pk output size x : \underline{15}, 18, 21, 28, 40, 42, 43,

44, 52. pk output size y : \underline{15}, 18, 21, 28, 31, 32, 34,

42, 52. pk total max x : \underline{19}, 21, 23. pk total max y : \underline{19}, 21, 23. pk total min x : \underline{19}, 21, 23. pk total min y : \underline{19}, 21, 23. pk width: \underline{15}, 21, 28, 34. : \underline{49}, 51. pos : \underline{46}, \underline{48}. : \underline{23}, 24. post adr : \underline{21}, 23, 24. : \underline{24}. : \underline{24}. ppp x : \underline{19}, 21, 23. ppp y : \underline{19}, 21, 23. : \underline{13}, 14. : 8, \underline{53}, 59. : \underline{53}, 59. printf : 4, 5, 6, 12, 18, 46, 48, 51, 55. prP : \underline{30}, 31, 32, 33. Q: \underline{65}. quiet : \underline{2}, 4, 7, 12, 18, 46, 48, 51, 55. : \underline{2}. read config : 4, \underline{54}, \underline{55}. read row : 27, 30, 32, 33, \underline{36}, \underline{37}. : \underline{2}, 55. real config file: \underline{55}. real hbf header : \underline{57}. remainder : \underline{48}. result : \underline{80}. rewind : 65. rm command : \underline{49}, 51, 59. rotation: \underline{15}, 28, 36, 37, 59. row : \underline{30}, 31, 34. rows read : \underline{30}, 32, 33. s: \underline{14}, \underline{46}, \underline{48}. s mag x : \underline{27}, 28, 34. s mag y : \underline{27}, 28, 30, 32, 33. s slant : \underline{27}, 28, 34. sc: \underline{46}, \underline{48}. : \underline{27}, 28, 30, 33, 34, 35. search string : \underline{65}. secs now : \underline{14}. setup list : \underline{74}, 75. skip: \underline{42}, 43. : \underline{41}, 43. : \underline{41}, 43. : \underline{41}, 43. : \underline{41}. slant : \underline{15}, 28, 46, 48, 52, 59. special adr : \underline{21}, 22, 23. sprintf : 12, 46, 48. start : \underline{42}. stderr : 7, 8, 12, 28, 46, 48, 51, 55, 57, 59,

66, 68, 75, 78. stdout : 18. strcat : 14, 51, 56. strcmp: 7. strcpy : 14, 51, 57, 59, 72. strdup: 80. strftime: 14. : \underline{2}, 19, 49, 53, 57, 65, 66. strlen: 4, 8, 14, 22, 46, 48. strncpy : 4, 59. strtol : 8. strtoul : 59. success : \underline{65}. t: \underline{46}, \underline{48}. target size x : \underline{15}, 28. target size y : \underline{15}, 28. temp: \underline{21}, 24. temp buffer : \underline{65}, 66. temp pixelrow : \underline{27}, 30. temp prP : \underline{30}, 31, 33, 34. testing : \underline{2}, 4, 7, 55. TeX search cfg file: 55, \underline{79}, \underline{80}. TeX search hbf file: 57, \underline{79}, \underline{80}. TeX search version: 5, \underline{71}, \underline{72}. tfm directory : \underline{49}, 51, 59. tfm files : \underline{2}, 4, 7, 51, 59. tfm header : \underline{46}. tfm offset x : \underline{15}, 21, 28, 46, 48. tfm offset y : \underline{15}, 28, 46, 48. tfm output size x : \underline{15}, 21, 28, 46, 48. tfm output size y : \underline{15}, 28, 46, 48. tfm width: 19, \underline{21}, 23. threshold : \underline{38}, 40, 59. time: 14. time now : \underline{14}. tm: 14. : 10. tmp: \underline{28}. tolower : 65. : \underline{2}, 4, 7, 9, 30, 59, 75, 80. unicode: \underline{2}, 8, 9, 12, 28, 46, 51, 59. : \underline{6}. used : 75. user min char : \underline{58}, 59, 61. val : \underline{75}. : 48, \underline{62}, 63. : \underline{5}. : \underline{27}, 42, 44. : \underline{2}, 12. write coding : 18, \underline{41}, \underline{42}. write data: 11, 12, 15, \underline{16}, \underline{17}. write file: 4, 9, \underline{11}, \underline{12}. write job: 4, \underline{50}, \underline{51}. write ovp: 4, \underline{47}, \underline{48}. write pl : 4, \underline{45}, \underline{46}, 47. write post : 11, 12, 19, \underline{20}, \underline{21}. write pre: 11, 12, \underline{13}, \underline{14}. write row : 30, 34, 35, 38, \underline{39}, \underline{40}. : \underline{2}, 46, 48, 51. x: \underline{42}. x resolution: \underline{2}, 4, 8, 12, 28, 52. xP : \underline{30}, 32, 33, 34, 35, \underline{37}, \underline{40}. : \underline{22}. : \underline{22}. : \underline{22}. : \underline{22}. y: \underline{42}. y scale: \underline{2}, 4, 8, 28, 52. : \underline{22}.

⟨ Check for environment variables 66 ⟩ Used in section 65. ⟨ Check other arguments 8 ⟩ Used in section 4.

⟨ Get code range 61 ⟩ Used in section 55. ⟨ Get sub code range 63 ⟩ Used in section 55. ⟨ Global variables 2, 15, 19, 27, 38, 49, 53, 58, 60, 62, 70, 73, 76 ⟩ Used in section 4. ⟨ Handle extension 56 ⟩ Used in section 55. ⟨ Include files 10, 69 ⟩ Used in section 4.

⟨ Initialize TEX file searching 78 ⟩ Used in section 4. ⟨ Initialize variables 28 ⟩ Used in section 4. ⟨ Necessary parameters 57 ⟩ Used in section 55. ⟨ Optional parameters 59 ⟩ Used in section 55.

⟨ Post section 23 ⟩ Used in section 21. ⟨ Postpost section 24 ⟩ Used in section 21.

⟨ Print help information 6 ⟩ Used in section 7.

⟨ Print version 5 ⟩ Used in section 7.

⟨ Process rest of line 44 ⟩ Used in section 42. ⟨ Produce a temporary row 33 ⟩ Used in section 32.

⟨ Prototypes 11, 13, 16, 20, 25, 29, 36, 39, 41, 45, 47, 50, 54, 64, 67, 71, 74, 79 ⟩ Used in section 4.

⟨ Scale X from temp pixelrow [ ] into new pixelrow [ ] and write it into out char [ ] 34 ⟩ Used in section 31. ⟨ Scale Y from pixelrow [ ] into temp pixelrow [ ] 32 ⟩ Used in section 31.

⟨ Scale row by row 31 ⟩ Used in section 30. ⟨ Scan options 7 ⟩ Used in section 4.

⟨ Search blank lines 43 ⟩ Used in section 42.

⟨ Special section 22 ⟩ Used in section 21. ⟨ Write character 18 ⟩ Used in section 17. ⟨ Write files 9 ⟩ Used in section 4. ⟨ Write out a row 35 ⟩ Used in section 34.

The hbf2gf program

(CJK Version 4.8.3)

Section Page

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 The main routine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 The functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 9 The font metrics file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 31 The extended virtual font file for Ω. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 34 The job file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 37 The configuration file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 40 File searching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 50 An example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 54 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 56

Copyright \begin{matrix}c \\ ◯ \end{matrix} 1996-1999 by Werner Lemberg

Permission is granted to make and distribute verbatim copies of this document provided that the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this document under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.