diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
commit | 487ca4806cc046076293cf6cc5fbba0db282bac7 (patch) | |
tree | 847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/dviljk/tfm.c | |
parent | a3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff) |
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dviljk/tfm.c')
-rw-r--r-- | Build/source/texk/dviljk/tfm.c | 288 |
1 files changed, 288 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..489340271a3 --- /dev/null +++ b/Build/source/texk/dviljk/tfm.c @@ -0,0 +1,288 @@ +/* $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> +extern char* TFMpath; +#endif + +#include "config.h" /* for STRSIZE and tfm_info_type, at least */ + /* and for IO-functions (since RISC OS) */ + +#ifdef NeedVarargsPrototypes +extern void Fatal(char *, ...); +#else +void Fatal(); +#endif + +#ifdef vms +#include <ssdef.h> +#include <stsdef.h> +#define getenv vms_getenv +#endif + +#if NeedFunctionPrototypes +# define DVIPROTO(x) x +#else +# define DVIPROTO(x) () +#endif + +/* Defined in dvi2xx.c. */ +extern long4 NoSignExtend DVIPROTO((FILEPTR, int)); + +#define TFM_GET_TWO() NoSignExtend (tfm_fp, 2) +#define TFM_GET_FOUR() NoSignExtend (tfm_fp, 4) + +extern bool G_quiet; +extern void Warning(); + +/* 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 +#if NeedFunctionPrototypes +tfm_get_n (FILEPTR tfm_fp, unsigned nwords, unsigned char **outbuf) +#else +tfm_get_n (tfm_fp, nwords, outbuf) + FILE *tfm_fp; + unsigned nwords; + void **outbuf; +#endif +{ + 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 +#if NeedFunctionPrototypes +get_bcpl (unsigned char *data, unsigned char *str) +#else +get_bcpl (data, str) +unsigned char *data; +unsigned char *str; +#endif +{ + 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 +#if NeedFunctionPrototypes +get_pcl_info (unsigned char *data, unsigned *spacing, unsigned *style, + int *weight, unsigned *typeface_id) +#else +get_pcl_info (data, spacing, style, weight, typeface_id) + unsigned char *data; + unsigned *spacing; + unsigned *style; + int *weight; + unsigned *typeface_id; +#endif +{ + /* 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 +#if NeedFunctionPrototypes +tfm_read_info (char *name, tfm_info_type *ret) +#else +tfm_read_info (name, ret) + char *name; + tfm_info_type *ret; +#endif +{ + /* 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; +} |