diff options
author | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
commit | ad547a6b5986815fda458221149728d9d9ab1d87 (patch) | |
tree | 16296910eb3eca724371474ea9aea3994dc69614 /Build/source/texk/dviljk/tfm.c | |
parent | 947b43de3dd21d58ccc2ffadefc4441ea1c2a813 (diff) |
restore Build,TODO from r57911
git-svn-id: svn://tug.org/texlive/trunk@57915 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dviljk/tfm.c')
-rw-r--r-- | Build/source/texk/dviljk/tfm.c | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/Build/source/texk/dviljk/tfm.c b/Build/source/texk/dviljk/tfm.c new file mode 100644 index 00000000000..0357a572735 --- /dev/null +++ b/Build/source/texk/dviljk/tfm.c @@ -0,0 +1,243 @@ +/* $Id: tfm.c,v 2.0 1996/05/12 22:25:04 neumann Exp $ */ +/* Read tfm widths resident font support in dvilj. Originally + written by kb@cs.umb.edu in early 1994. Public domain. */ + +#ifdef KPATHSEA +#include <kpathsea/config.h> +#include <kpathsea/c-fopen.h> +#include <kpathsea/lib.h> +#include <kpathsea/tex-file.h> +#include <c-auto.h> +#else +#include <stdio.h> +#include <stdlib.h> +#endif + +#include "config.h" /* for STRSIZE and tfm_info_type, at least */ + /* and for IO-functions (since RISC OS) */ + +#include "tfm.h" + +#ifdef vms +#include <ssdef.h> +#include <stsdef.h> +#define getenv vms_getenv +#endif + +#define TFM_GET_TWO() NoSignExtend (tfm_fp, 2) +#define TFM_GET_FOUR() NoSignExtend (tfm_fp, 4) + +/* Read N words (N * 4 bytes) from TFM_FP and return it in *OUTBUF, unless + OUTBUF==NULL, in which case throw them away. */ + +static void +tfm_get_n (FILEPTR tfm_fp, unsigned nwords, unsigned char **outbuf) +{ + unsigned n = nwords * 4; + void *buf = (void *) malloc (n); + + if (buf == NULL) {BCLOSE(tfm_fp); Fatal("(tfm): out of memory error!\n");} + read_multi (buf, 1, n, tfm_fp); + if (FEOF(tfm_fp)) { + BCLOSE(tfm_fp); Fatal("dvilj(tfm): Could not read %u bytes from TFM file.\n", n); + exit (1); + } + + /* If OUTBUF is null, free what we just read, else return it. */ + if (outbuf) { + *outbuf = buf; + } else { + free (buf); + } +} + + +/* Read a string in BCPL format from DATA into STR, and terminate with a + null byte. First byte of DATA says how many characters follow. + Assume STR is long enough. */ + +static void +get_bcpl (unsigned char *data, unsigned char *str) +{ + unsigned length; + + for (length = *(data ++); length; length --) { + *(str ++) = *(data ++); + } + *str = 0; +} + +/* Header word 18: + 2 bytes: "KN" for Karl and Norm---this identifies our extensions + 1 byte : 1 if proportional, 0 otherwise + 1 byte : reserved (to extend the style, if necessary) + Header word 19: + 2 bytes: PCL style selection number + 1 byte : reserved (to extend weight, if necessary) + 1 byte : weight (signed, 2's complement, valid -7 to +7) + Header word 20: + 2 bytes: reserved (to extend typeface id, if necessary) + 2 bytes: PCL typeface selection number + + The first (BigEndian) byte of header word #18 is DATA[0]. + Assume DATA is long enough for everything we might try to read. */ + +static bool +get_pcl_info (unsigned char *data, unsigned *spacing, unsigned *style, + int *weight, unsigned *typeface_id) +{ + /* No magic number for our extensions => forget it. */ + if (data[0] != 'K' && data[1] != 'N') + return _FALSE; + + *spacing = data[(0* 4) + 2]; /* Third byte of first word. */ + + /* First two bytes of second word. */ + *style = (data[(1 * 4)] << 8) + data[(1 * 4) + 1]; + + /* Last byte of second word, signed two-complement. */ + *weight = data[(1 * 4) + 3]; + if (*weight >= 128) *weight -= 256; + + /* Effectively all four bytes of third word. */ + *typeface_id = (data[(2 * 4) + 0] << 24) + (data[(2 * 4) + 1] << 16) + + (data[(2 * 4) + 2] << 8) + (data[(2 * 4) + 3]); + + return _TRUE; +} + +/* If the TFM file NAME exists, set the elements of RET and return true. + Otherwise, return false. */ + +bool +tfm_read_info (char *name, tfm_info_type *ret) +{ + /* Don't use a structure for this, since then it might occupy more + than the exactly four bytes that we need. */ + unsigned char *char_info; + FILEPTR tfm_fp; + unsigned char *header_data; + unsigned char *width_raw; /* array of 1-byte data */ + unsigned long4 *width_table; /* array of 4-byte fixes */ + unsigned i; + unsigned lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np; +#ifdef KPATHSEA + char *full_name = kpse_find_tfm (name); + + if (full_name == NULL) { + return _FALSE; + } + tfm_fp = xfopen (full_name, FOPEN_RBIN_MODE); +#else /* not KPATHSEA */ + char full_name[STRSIZE]; + if (findfile(TFMpath, name, 0, full_name, _TRUE, 0)) { + + /* fprintf(ERR_STREAM,"full_name=<%s>\n", full_name);*/ + tfm_fp = BINOPEN(full_name); + if (tfm_fp == FPNULL) { + /* this can happen, if the calculation for max number of open + * files has to be corrected + */ + fprintf(ERR_STREAM,"Error: file <%s> could not be opened\n", full_name); + return _FALSE; + } + } else { + Warning("tfm file %s.tfm not found on path <%s>\n", name, TFMpath); + return _FALSE; + } +#endif /* not KPATHSEA */ + + (void) TFM_GET_TWO (); /* word length of file */ + lh = TFM_GET_TWO (); /* words of header data */ + bc = TFM_GET_TWO (); /* smallest character code */ + ec = TFM_GET_TWO (); /* largest character code */ + nw = TFM_GET_TWO (); /* words in width table */ + nh = TFM_GET_TWO (); /* words in height table */ + nd = TFM_GET_TWO (); /* words in depth table */ + ni = TFM_GET_TWO (); /* words in italic correction table */ + nl = TFM_GET_TWO (); /* words in lig/kern table */ + nk = TFM_GET_TWO (); /* words in kern table */ + ne = TFM_GET_TWO (); /* words in extensible char table */ + np = TFM_GET_TWO (); /* words of font parameter data */ + + tfm_get_n (tfm_fp, lh, &header_data); + /* Only two headerbyte words are required by the TFM format, so don't + insist on all this extra stuff. */ + if (lh > 2) { + get_bcpl (header_data + (2 * 4), ret->coding_scheme); + } else { + ret->coding_scheme[0] = 0; + } + + if (lh > 12) { + get_bcpl (header_data + (12 * 4), ret->family); + } else { + ret->family[0] = 0; + } + + /* Sorry for the convoluted logic. The idea is that if the family + is HPAUTOTFM, we better have our extensions -- so if we don't + have enough header words, or if we don't find what we need in + the header words, something's seriously wrong, and we shouldn't + claim to have succeeded at reading a good TFM file. */ + + if (strcmp ((char *)ret->family, "HPAUTOTFM") == 0 + && (lh < 20 + || !get_pcl_info (&(header_data[18 * 4]), + &ret->spacing, &ret->style, &ret->weight, + &ret->typeface_id))) { + BCLOSE (tfm_fp); + return _FALSE; + } + + /* Initialize our returned array of widths to zero, since the TFM file + need not contain info for all character codes. */ + for (i = 0; i < bc; i++) { + ret->widths[i] = 0; + } + for (i = ec + 1; i < 256; i++) { + ret->widths[i] = 0; + } + + /* The char_info is one word (four bytes) for each character in the font. */ + tfm_get_n (tfm_fp, ec - bc + 1, &char_info); + + /* The width table is just nw words. */ + tfm_get_n (tfm_fp, nw, &width_raw); + width_table = (unsigned long4 *) malloc (nw * 4); + if (width_table == NULL) {BCLOSE(tfm_fp); Fatal("dvilj(tfm): out of memory!\n");} + + /* But the width table contains four-byte numbers, so have to convert + from BigEndian to host order. */ + for (i = 0; i < nw; i++) { + unsigned byte_offset = i * 4; + unsigned b1 = width_raw[byte_offset]; + unsigned b2 = width_raw[byte_offset + 1]; + unsigned b3 = width_raw[byte_offset + 2]; + unsigned b4 = width_raw[byte_offset + 3]; + width_table[i] = (b1 << 24) + (b2 << 16) + (b3 << 8) + b4; + } + + /* For each character, retrieve and store the TFM width. */ + for (i = bc; i <= ec; i++) { + unsigned char w_i = char_info[(i - bc) * 4]; + ret->widths[i] = width_table[w_i]; + } + + /* Throw away everything up to the second font parameter. (Could just + seek, but I don't want to pull in the include files, etc.) */ + if (np >= 2) { + tfm_get_n (tfm_fp, nh + nd + ni + nl + nk + ne + 1, NULL); + ret->interword = TFM_GET_FOUR (); + } else { + ret->interword = 0; + } + + free (header_data); + free (char_info); + free (width_raw); + free (width_table); + + BCLOSE (tfm_fp); + return _TRUE; +} |