summaryrefslogtreecommitdiff
path: root/dviware/ln03/rose/dvi2ln3nft.c
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/ln03/rose/dvi2ln3nft.c')
-rw-r--r--dviware/ln03/rose/dvi2ln3nft.c1145
1 files changed, 1145 insertions, 0 deletions
diff --git a/dviware/ln03/rose/dvi2ln3nft.c b/dviware/ln03/rose/dvi2ln3nft.c
new file mode 100644
index 0000000000..dd6e0983b1
--- /dev/null
+++ b/dviware/ln03/rose/dvi2ln3nft.c
@@ -0,0 +1,1145 @@
+/* This file contains those portions of Dvi2ln3 that create font loads. It
+is still being developed...
+
+Copyright (c) 1983, 1984, 1985, 1986 by Digital Equipment Corporation.
+Author: Flavio Rose, ...!decwrl!dec-rhea!dec-dvinci!rose.
+
+Development chronology:
+
+11/28/84: Initial version in PL/I. Finished 11/30/84.
+ 3/4/85: C translation, a prelude to writing DVI2LN3.
+ 5/7/85: Finally got around to debugging the C translation!
+ 6/5/85: Convert to work with Dvi2ln3 -- minor changes.
+ 6/18/85: Try not to use big input array.
+ 6/22/85: Cleanup, try to identify longs.
+11/12/85: Changed to read PXLs rather than LN03 format files. Old file
+ called dvi2ln3nft, now renamed to dvi2ln3pxl.
+11/15/85: More optimized PXL reading -- use lnf instead of the pxlbuf
+ when reading rasters. Return just status value from add_txf_...,
+ use ras_len_added to communicate size. Facilitate error
+ recovery with copy_ersatz_char. LN03 file reading functionality
+ woven back in.
+ 1/16/86: Embarrassing bug, forgot to close the nftf after done with it.
+ 3/28/86: Conditionalization for Ultrix.
+ 4/7/86: After moving this to 4.3bsd at MIT, a couple more
+ fixes to the portability.
+
+*/
+
+/* INTRODUCTION: When writing an LN03 driver for TeX, it must be kept in
+mind that the LN03 has limited font storage capability. The standard LN03
+has just 27k bytes, and two 128k byte RAM cartridges may be added.
+
+For this reason, when we convert a DVI file to LN03 form, we build a
+special font load that has just the glyphs that the DVI file needs. This
+allows very complex files, e.g. the first nine chapters of the
+Metafontbook, to be printed on LN03s that have just one extra RAM
+cartridge. This approach does, however, consume considerable resources in
+the VAX to build those font loads. */
+
+/* The following is customary boilerplate. */
+
+#ifdef vms
+#include stdio
+#else
+#include <stdio.h>
+#endif
+
+/* In VMS we declare external variables to be globalref.
+This is not really necessary, just an old habit. */
+
+#ifdef vms
+#define GLOBAL globaldef
+#define EXTERN globalref
+#else
+#define GLOBAL
+#define EXTERN extern
+#endif
+
+/* The following symbols are declared compatibly with those in the file
+Dvi2ln3.c. */
+
+#define maxnfonts 31
+#define MAXTEXFONTS 100
+#define FILESPECLEN 252
+#define leftfirst 33
+#define leftlast 126
+#define rightfirst 161
+#define rightlast 254
+
+EXTERN FILE *outfile;
+EXTERN int lastch[maxnfonts];
+EXTERN unsigned char chw[maxnfonts][256];
+
+struct txf { unsigned char chu[256]; int bc, ec; long space, design_size,
+ scaled_size; int nchs; };
+EXTERN struct txf *txfa[MAXTEXFONTS+1];
+EXTERN long int *font_width[MAXTEXFONTS+1];
+
+EXTERN char *font_name[MAXTEXFONTS+1];
+EXTERN float conv, unmag_conv;
+
+#ifndef vms
+char *getenv();
+#endif
+
+/* The LN03 font load we build is buffered in a fixed-size area, slightly
+smaller than the maximum amount of font memory available on an LN03. [[The
+code should be changed to chain fixed-size buffers, so font loads of
+unlimited size can be handled, subject only to memory availability. On
+systems with limited memory, it may be desirable to use a disk file instead
+of this buffer.]] */
+
+#define OBUFLEN 2*256*256
+GLOBAL unsigned char lnf[OBUFLEN];
+
+/* While constructing the font load, we keep track of the length of the
+"character definitions area" in ras_len. We also have to keep track of the
+raster size measured in three different ways, as psize (portrait), lsize
+(landscape), and msize (mixed). This is required to fill certain fields in
+the font load. */
+
+GLOBAL long int ras_len,psize,lsize,msize;
+
+/* The font load that we construct consists of a number of LN03 fonts. Each
+of these contains up to 94 glyphs. They may be "left fonts", so their
+glyphs are invoked with codes 33 through 126; or they may be "right fonts"
+that respond to codes 161 through 254.
+
+The font load that we construct is made up of alternating left and right
+fonts (sometimes called "font pairs"). A TeX font (represented by a txf
+record) is added to a font pair. It may be split between the left and right
+halves of the pair.
+
+The variable using_r keeps track of whether we are using a right font. */
+
+GLOBAL char using_r;
+
+GLOBAL unsigned int nft_first_ch,nft_last_ch,chardir_offset;
+GLOBAL int lnf_chardir,ras_beg;
+GLOBAL long ras_len_added;
+
+GLOBAL int pxlf,nftf;
+
+/* The purpose of add_txf_to_lnf is to read the PXL or LN03 font file
+corresponding to TeX font txfno and add its rasters to the font pair
+referred to by lnfno. The function returns 0 if all went well, and various
+negative numbers to indicate problems. The number of bytes added to the
+font load is returned in the global ras_len_added. */
+
+int add_txf_to_lnf(lnfno,txfno)
+int lnfno,txfno;
+{
+ int i,j,k,l,width;
+ int first_txfc,last_txfc;
+ char first_txf,last_txf;
+
+ ras_len_added = 0;
+
+ if (txfno < 0 || txfno > MAXTEXFONTS || txfa[txfno] == 0 ||
+ lnfno < 0 || lnfno > maxnfonts) {
+ printf("\nDvi2ln3 internal error, bad txfno or lnfno");
+ goto error_return;
+ }
+
+/* Now, compute first_txfc and last_txfc, the first and last characters
+codes to be copied from the TeX font. */
+
+ first_txfc = -1; last_txfc = -1;
+ for (i=0; i<256; i++) {
+ if (txfa[txfno] -> chu[i] != 0) {
+ if (first_txfc == -1) first_txfc = i;
+ last_txfc = i;
+ }
+ }
+ if (first_txfc == -1 || last_txfc == -1) return(0);
+
+/* Tell user what font is being loaded */
+
+ printf("\nLoading font %s",font_name[txfno]);
+ k = (1500.0*conv*txfa[txfno] -> scaled_size)/
+ (unmag_conv*txfa[txfno] -> design_size) + 0.5;
+ l = ((float)k)/15.0 + 0.5;
+ if (l != 100) printf(" (magnified %d%%)",l);
+
+/* Now open the file from which we are getting rasters. We look first for a
+PXL file, then for an LN03 format font file (NFT file). */
+
+ pxlf = -1;
+ nftf = -1;
+ open_nft_file(txfno);
+ if (nftf == -1) open_pxl_file(txfno);
+
+/* If neither a PXL file nor an LN03 format file could be opened, warn the
+user. The font load will be filled in with blanks nonetheless. */
+
+ if (pxlf == -1 && nftf == -1)
+ printf("\n Couldn't find good font file: using blanks");
+
+/* Now replace first_txfc and last_txfc by the character codes into which
+they are going to be copied. */
+
+ first_txfc = txfa[txfno] -> chu[first_txfc];
+ last_txfc = txfa[txfno] -> chu[last_txfc];
+
+/* Determine if this is the first or last TeX font that is being copied
+into the current LN03 font pair. */
+
+ first_txf = (first_txfc == leftfirst);
+ last_txf = (last_txfc == lastch[lnfno]);
+
+/* If this is the first TeX font for the current LN03 font pair, then we
+have to initialize the LN03 font load buffer. The initialization routine
+computes where the rasters begin in the output buffer, puts in the blanks,
+etc. */
+
+ if (first_txf) {
+ using_r = 0;
+ initialize_lnf(lnfno);
+ }
+
+/* Now go through all the characters in the TeX font and copy their rasters
+into the appropriate positions in the LN03 font pair. When we copy the the
+last rasters into the left font, we write the font out and then a comma to
+separate it from the next font. [[Fencepost error?]] */
+
+ for (i=0; i<256; i++) {
+ if (txfa[txfno] -> chu[i] != 0) {
+ j = txfa[txfno] -> chu[i];
+ if (!using_r && j >= rightfirst) {
+ write_lnf();
+ fprintf(outfile,"\n,");
+ using_r = 1;
+ initialize_lnf(lnfno);
+ }
+ if (pxlf != -1) {
+ k = copy_pxl_char(i,j,lnfno);
+ if (k != 0) {
+ close(pxlf);
+ pxlf = -1;
+ }
+ } else if (nftf != -1) {
+ k = copy_nft_char(i,j,lnfno);
+ if (k != 0) {
+ close(nftf);
+ nftf = -1;
+ }
+ }
+ if (pxlf == -1 && nftf == -1) {
+ width = font_width[txfno][i]*conv+0.5;
+ k = copy_ersatz_char(j,lnfno,width);
+ }
+ }
+ }
+
+ if (nftf != -1) close(nftf);
+ if (pxlf != -1) close(pxlf);
+
+/* If this is the last TeX font being added to this LN03 font pair, write
+out the current font (right or left) from the pair. */
+
+ if (last_txf) write_lnf();
+
+/* Type and return the incremental amount of space that the TeX font being
+added takes up in the output font load. */
+
+ ras_len_added += 4*(txfa[txfno] -> nchs);
+ printf(", %d bytes",ras_len_added);
+
+ return(0);
+
+error_return:
+ return(-1);
+
+}
+
+/* A buffer is used to hold the directory part of the PXL file. */
+
+#define PXLBUFSIZE 4*517
+
+GLOBAL unsigned char pxlbuf[PXLBUFSIZE];
+GLOBAL long pxllen;
+
+/* The value pxlconv is computed to be the correct conversion factor from the
+widths in the PXL file, which are expressed in units of 2^-20 times the
+design size, to pixels. */
+
+GLOBAL float pxlconv;
+
+/* As usual when dealing with TeX files, we have to rearrange bytes in
+an overlay to combine them into longwords. The reason for this is that
+bytes in TeX files are combined into longwords the opposite way from how
+the VAX combines them.
+
+Hence, the following overlay and macro: */
+
+GLOBAL union lc { unsigned long int ul;
+ long int l;
+ unsigned char c[4]; } lcy;
+
+#define copy_from_lnf(i) lcy.c[0] = lnf[i]; lcy.c[1] = lnf[i+1]; \
+ lcy.c[2] = lnf[i+2]; lcy.c[3] = lnf[i+3]
+#define copy_to_lnf(i) lnf[i] = lcy.c[0]; lnf[i+1] = lcy.c[1]; \
+ lnf[i+2] = lcy.c[2] ; lnf[i+3] = lcy.c[3]
+#define copy_from_pxl(_x) { lcy.c[3] = pxlbuf[_x]; \
+ lcy.c[2] = pxlbuf[(_x)+1]; lcy.c[1] = pxlbuf[(_x)+2]; \
+ lcy.c[0] = pxlbuf[(_x)+3]; }
+
+/* open_pxl_file reads the last 517 longwords of the PXL file into the
+pxlbuf. */
+
+int open_pxl_file(txfno)
+int txfno;
+{
+
+ long i,j;
+ float two_to_the_20th = 0x100000;
+ int k,l,jnam,jext,target;
+ char fullspec[FILESPECLEN];
+#ifndef vms
+ char *pxldir;
+#endif
+
+ find_filename(font_name[txfno],&jnam,&jext);
+
+ fullspec[0] = '\0';
+#ifdef vms
+ if (jnam == 0) strcpy(fullspec,"TEX$PXLDIR:");
+#else
+ if (jnam == 0) {
+ pxldir = getenv("TEX_PXLDIR");
+ strcpy(fullspec,pxldir);
+ strcat(fullspec,"/");
+ }
+#endif
+ strcat(fullspec,font_name[txfno]);
+ k = (1500.0*conv*txfa[txfno] -> scaled_size)/
+ (unmag_conv*txfa[txfno] -> design_size) + 0.5;
+ l = strlen(fullspec);
+ sprintf(&fullspec[l],".%dpxl\0",k);
+
+ pxllen = 0;
+ pxlf = open(fullspec,0);
+ if (pxlf == -1) return(1);
+
+ lseek(pxlf,-517*4,2);
+ i = read(pxlf,pxlbuf,517*4);
+ if (i != 517*4) {
+ printf("\n Error while reading PXL file");
+ close(pxlf);
+ pxlf = -1;
+ return(1);
+ }
+ pxllen = 4*517;
+
+/* Now that we have read the PXL file, check that it is in correct format
+by looking for a trailing ID byte of 1001. */
+
+ copy_from_pxl(pxllen-4);
+ if (lcy.ul != 1001) {
+ printf("\n Error while reading PXL file");
+ close(pxlf);
+ pxlf = -1;
+ return(1);
+ }
+
+/* If the format is correct, derive a scale factor for the widths. */
+
+ copy_from_pxl(pxllen-12);
+ pxlconv = lcy.ul;
+ copy_from_pxl(pxllen-16);
+ pxlconv = (pxlconv/two_to_the_20th)*(lcy.ul/5.0)
+ *(1.0/(72.27*two_to_the_20th));
+ return(0);
+
+}
+
+GLOBAL unsigned char rev_byte[256] = {
+ 0,128,64,192,32,160,96,224,
+ 16,144,80,208,48,176,112,240,
+ 8,136,72,200,40,168,104,232,
+ 24,152,88,216,56,184,120,248,
+ 4,132,68,196,36,164,100,228,
+ 20,148,84,212,52,180,116,244,
+ 12,140,76,204,44,172,108,236,
+ 28,156,92,220,60,188,124,252,
+ 2,130,66,194,34,162,98,226,
+ 18,146,82,210,50,178,114,242,
+ 10,138,74,202,42,170,106,234,
+ 26,154,90,218,58,186,122,250,
+ 6,134,70,198,38,166,102,230,
+ 22,150,86,214,54,182,118,246,
+ 14,142,78,206,46,174,110,238,
+ 30,158,94,222,62,190,126,254,
+ 1,129,65,193,33,161,97,225,
+ 17,145,81,209,49,177,113,241,
+ 9,137,73,201,41,169,105,233,
+ 25,153,89,217,57,185,121,249,
+ 5,133,69,197,37,165,101,229,
+ 21,149,85,213,53,181,117,245,
+ 13,141,77,205,45,173,109,237,
+ 29,157,93,221,61,189,125,253,
+ 3,131,67,195,35,163,99,227,
+ 19,147,83,211,51,179,115,243,
+ 11,139,75,203,43,171,107,235,
+ 27,155,91,219,59,187,123,251,
+ 7,135,71,199,39,167,103,231,
+ 23,151,87,215,55,183,119,247,
+ 15,143,79,207,47,175,111,239,
+ 31,159,95,223,63,191,127,255
+ };
+
+#define pxl_word(_x) (pxlbuf[_x]*256+pxlbuf[(_x)+1])
+#define signed_pxl_word(_x) ((pxl_word(_x)>0x8000) ? \
+ (pxl_word(_x)-0x10000) : pxl_word(_x))
+
+/* Copy_pxl_char copies the rasters and character directory information
+corresponding to code from in the PXL file, into the to position of the
+LN03 font load buffer. */
+
+int copy_pxl_char(from,to,lnfno)
+unsigned char from,to;
+int lnfno;
+{
+
+ unsigned long ds,rs,i,j,def_start;
+ unsigned int rows,cols,k,l,m,n;
+ int xoffset, yoffset;
+ int width;
+ char all_blank;
+
+/* Check if the character code from is in the right range for the PXL file.
+*/
+
+ if (from > 127) return(1);
+
+/* Locate the definition and the rasters for from in the PXL file. */
+
+ ds = 16*from;
+ copy_from_pxl(ds+8);
+ rs = 4*lcy.ul;
+ cols = pxl_word(ds); rows = pxl_word(ds+2);
+
+/* If a glyph has no rasters, an "undocumented feature" of the LN03 seems
+to cause the glyph to be printed incorrectly. Because of this, we set the
+number of rows and columns to 1, and put in a blank byte (below). */
+
+ all_blank = ((rows == 0) & (cols == 0)) | rs == 0;
+ if (all_blank) {
+ cols = 1;
+ rows = 1;
+ }
+
+/* Compute the width of the glyph in pixels, the xoffset, and the yoffset.
+*/
+
+ copy_from_pxl(ds+12);
+ width = pxlconv*lcy.ul+0.5;
+ xoffset = signed_pxl_word(ds+4);
+ yoffset = signed_pxl_word(ds+6);
+ chw[lnfno][to] = width;
+
+/* Check that we have enough room left in the LN03 font load buffer. Fudge
+factor of 3 added because the read below may read too much. */
+
+ def_start = ras_beg+ras_len;
+ if (def_start+rows*((cols+7)/32)+24+3 > OBUFLEN) {
+ printf("\nNo more room in LN03 font load buffer (%ld bytes long)",
+ OBUFLEN);
+ return(1);
+ }
+
+/* Clear the character definition area in the LN03 font load buffer. */
+
+ for(i=0; i<24+rows*((cols+7)/8); i++)
+ lnf[def_start+i] = 0;
+
+/* Set the fields in the first six longwords of the LN03 font load
+character definition. The first assignment sets the so-called "flag flag",
+which must be always be set according to the Common Font File Format. A
+conversion factor of 24 is used in converting pixel values, because the
+values are supposed to be in centipoints in the LN03 font load, and if we
+assume there are 300 pixels in an inch, then there are 7200 centipoints in
+an inch. */
+
+ lnf[def_start+3] = 0x80;
+ lcy.ul = 24*width;
+ copy_to_lnf(def_start+4);
+ lcy.l = -24*xoffset;
+ copy_to_lnf(def_start+8);
+ lcy.l = -24*yoffset;
+ copy_to_lnf(def_start+12);
+
+/* The rasters are always placed in portrait into the LN03 font load, with
+no use of run-length encoding. Thus, the orient field in the raster format
+will be 0, and the Type 1 field is set to 0x81. */
+
+ lnf[def_start+17] = 0x81;
+ lnf[def_start+20] = rows%256;
+ lnf[def_start+21] = rows/256;
+ lnf[def_start+22] = cols%256;
+ lnf[def_start+23] = cols/256;
+
+/* Now we copy the rasters themselves. As we do so, we have to reverse
+the bits within each byte. */
+
+ k = (cols+31)/32;
+ n = (cols+7)/8;
+ lseek(pxlf,rs,0);
+ if (!all_blank) {
+ for (l=0; l<rows; l++) {
+ read(pxlf,&lnf[def_start+24+n*l],4*k);
+ }
+ for (m=0; m<n*rows; m++)
+ lnf[def_start+24+m] = rev_byte[lnf[def_start+24+m]];
+ }
+
+/* Set the character locator, increment the LN03 font load buffer length,
+and recompute the three sizes. */
+
+ lcy.l = def_start;
+ if (to <= leftlast) i = to-leftfirst; else i = to-rightfirst;
+ copy_to_lnf(lnf_chardir+4*i);
+ ras_len += 24+rows*n;
+ ras_len_added += 24+rows*n;
+ if (ras_len%2 == 1) {
+ lnf[ras_beg+ras_len] = 0;
+ ras_len++;
+ ras_len_added++;
+ }
+
+ i = rows*((cols+7)/8);
+ psize += i;
+ j = ((rows+7)/8)*cols;
+ lsize += j;
+ msize += (i > j) ? i : j;
+
+ return(0);
+}
+
+/* Write a blank character of specified width (in pixels) into LN03 font
+load buffer. Also, set the chw array. [[This function is a bit excessive.
+If we couldn't find a character's rasters, it would suffice just to leave
+the character locator blank.]] */
+
+int copy_ersatz_char(to,lnfno,width)
+unsigned char to;
+int lnfno,width;
+{
+
+ unsigned long ds,rs,i,j,def_start;
+ unsigned int rows,cols,k,l,m,n;
+
+ cols = 1;
+ rows = 1;
+ chw[lnfno][to] = width;
+
+/* Check that we have enough room left in the LN03 font load buffer. Return
+silently if not. */
+
+ def_start = ras_beg+ras_len;
+ if (def_start+rows*((cols+7)/32)+24 > OBUFLEN) return(1);
+
+/* Clear the character definition area in the LN03 font load buffer. */
+
+ for(i=0; i<24+rows*((cols+7)/8); i++)
+ lnf[def_start+i] = 0;
+ lnf[def_start+3] = 0x80;
+ lcy.ul = 24*width;
+ copy_to_lnf(def_start+4);
+
+/* The rasters are always placed in portrait into the LN03 font load, with
+[no use of run-length encoding. Thus, the orient field in the raster format
+will be 0, and the Type 1 field is set to 0x81. */
+
+ lnf[def_start+17] = 0x81;
+ lnf[def_start+20] = rows%256;
+ lnf[def_start+21] = rows/256;
+ lnf[def_start+22] = cols%256;
+ lnf[def_start+23] = cols/256;
+
+/* Set the character locator, increment the LN03 font load buffer length,
+and recompute the three sizes. */
+
+ n = (cols+7)/8;
+ lcy.l = def_start;
+ if (to <= leftlast) i = to-leftfirst; else i = to-rightfirst;
+ copy_to_lnf(lnf_chardir+4*i);
+ ras_len += 24+rows*n;
+ ras_len_added += 24+rows*n;
+ if (ras_len%2 == 1) {
+ lnf[ras_beg+ras_len] = 0;
+ ras_len++;
+ ras_len_added++;
+ }
+
+ i = rows*((cols+7)/8);
+ psize += i;
+ j = ((rows+7)/8)*cols;
+ lsize += j;
+ msize += (i > j) ? i : j;
+
+ return(0);
+}
+
+/* The opening part of each NFT file is copied into the array nfta.
+Nftlen keeps track of how much of the NFT file we have read. Nftf
+is the file descriptor used to do the reading. */
+
+GLOBAL unsigned char nfta[480+1024];
+GLOBAL long nftlen;
+
+#define copy_from_nft(i) lcy.c[0] = nfta[i]; lcy.c[1] = nfta[i+1]; \
+ lcy.c[2] = nfta[i+2]; lcy.c[3] = nfta[i+3]
+
+/* Open_nft_file opens the NFT file and reads the opening part into the NFT
+array. */
+
+int open_nft_file(txfno)
+int txfno;
+{
+ int k,l,jnam,jext,target;
+ char fullspec[FILESPECLEN];
+#ifndef vms
+ char *ln3dir;
+#endif
+
+ find_filename(font_name[txfno],&jnam,&jext);
+
+ fullspec[0] = '\0';
+#ifdef vms
+ if (jnam == 0) strcpy(fullspec,"TEX$LN03DIR:");
+#else
+ if (jnam == 0) {
+ ln3dir = getenv("TEX_LN03DIR");
+ strcpy(fullspec,ln3dir);
+ strcat(fullspec,"/");
+ }
+#endif
+ strcat(fullspec,font_name[txfno]);
+ k = (100.0*conv*txfa[txfno] -> scaled_size)/
+ (unmag_conv*txfa[txfno] -> design_size) + 0.5;
+ if (k == 100) strcat(fullspec,".nft");
+ else {
+ l = strlen(fullspec);
+ if (k < 1000) sprintf(&fullspec[l],".%03d\0",k);
+ else sprintf(&fullspec[l],".%d\0",k);
+ }
+
+ nftlen = 0;
+ nftf = open(fullspec,0);
+ if (nftf == -1) return(1);
+
+ if (read_nft_with_retry(nfta,480) != 0) {
+ close(nftf);
+ nftf = -1;
+ return(1);
+ }
+
+/* The NFT file might be random, or it might be a Common Font File Format
+file that isn't loadable into an LN03. So, we make a few checks.
+
+The second longword must be 'FONT'. */
+
+ if (nfta[4] != 'F' || nfta[5] != 'O' || nfta[6] != 'N'
+ || nfta[7] != 'T') {
+ printf(" -- Bad NFT file, lacks FONT.");
+ close(nftf);
+ nftf = -1;
+ return(1);
+ }
+
+/* We also check that there are a full 16 bytes of character parameters. If
+there are fewer, we give up: LN03s need all sixteen, and it's too hard to
+figure out how to give the missing ones reasonable values.
+
+Throughout this program, we define some constants beginning with fnt__
+which define byte offsets into the nft file. [[The long prefixes of these
+may cause some trouble if one's C compiler does not recognize too many
+significant characters in identifiers.]] */
+
+#define fnt__l_parameters_size 200
+
+ copy_from_nft(fnt__l_parameters_size);
+ if (lcy.l != 16) {
+ printf(" -- bad NFT file, not enough character parameters");
+ close(nftf);
+ nftf = -1;
+ return(1);
+ }
+
+/* Set the variable that tells us the starting location of the
+character directory. */
+
+ chardir_offset = 480;
+
+/* Figure out what the first and last character codes in the NFT file are.
+*/
+
+#define fnt__l_first_character 164
+
+ copy_from_nft(fnt__l_first_character);
+ nft_first_ch = lcy.l;
+ copy_from_nft(fnt__l_first_character+4);
+ nft_last_ch = lcy.l;
+
+/* We must have 0 <= nft_first_ch <= nft_last_ch <= 255, otherwise we
+give up on the NFT file. */
+
+ if (!((0 <= nft_first_ch) && (nft_first_ch <= nft_last_ch) &&
+ (nft_last_ch <= 255))) {
+ printf(" -- bad NFT file, bad character range.");
+ close(nftf);
+ nftf = -1;
+ return(1);
+ }
+
+/* Now read the character directory into the nfta. */
+
+ target = chardir_offset+4*(nft_last_ch+1-nft_first_ch);
+ if (read_nft_with_retry(&nfta[480],target) != 0) {
+ close(nftf);
+ nftf = -1;
+ return(1);
+ }
+ return(0);
+}
+
+/* Copy_nft_char copies the character parameters and rasters corresponding
+to the from argument out of the NFT file and into the LN03 font buffer. It
+also updates the chw (character width) array. */
+
+int copy_nft_char(from,to,lnfno)
+unsigned char from,to;
+int lnfno;
+{
+
+ int rows,columns,quo;
+ long i,j,len,def_start,target;
+
+/* Replace from by the first character code if the NFT file has no rasters
+for code from. If this is done, the output will of course be mangled. The
+user has already been warned above, so no further message is needed. */
+
+ if (from < nft_first_ch) from = nft_first_ch;
+ if (from > nft_last_ch) from = nft_last_ch;
+
+/* First we need to determine def_start, the byte offset of the character
+definition for code from in the NFT file */
+
+ copy_from_nft(chardir_offset+(from-nft_first_ch)*4);
+ def_start = lcy.l;
+
+/* If the locator is earlier in the file, just give up. Otherwise, assume
+it's good, continue and give a vague error message is something goes wrong.
+*/
+
+ if (def_start < nftlen || read_nft_until(def_start) != 0) {
+ printf("\n LN03 font file bad, using blanks");
+ return(1);
+ }
+
+/* Read the first 24 bytes of character data. */
+
+ def_start = ras_beg+ras_len;
+ if (read_nft_with_retry(&lnf[def_start],nftlen+24) != 0) return(1);
+
+/* Now we need to check that the rasters are uncompressed. LN03s can't
+accept compressed rasters, and this program isn't clever enough to
+decompress them. */
+
+ if (lnf[def_start+17] != 129) {
+ printf("\n LN03 font file bad, using blanks");
+ return(1);
+ }
+
+/* Fill in the chw array (which holds character widths). Centipoint to
+pixel conversion is necessary (there are 24 centipoints in a pixel), with
+rounding (hence the 12). */
+
+ copy_from_lnf(def_start+4);
+ chw[lnfno][to] = (lcy.l+12)/24;
+
+/* NFT files may contain character widths which are not integral numbers of
+pixels. It is necessary to round such values to pixels when copying into
+the final font load -- if sent unrounded to the LN03, the widths will be
+truncated and positions will be off in the printed output. */
+
+ lcy.l = 24*chw[lnfno][to];
+ copy_to_lnf(def_start+4);
+
+/* Now we need to compute the size of the rasters, and copy that number of
+bytes into the LN03 font buffer. */
+
+ rows = lnf[def_start+20]+256*lnf[def_start+21];
+ columns = lnf[def_start+22]+256*lnf[def_start+23];
+
+/* We have to update psize, lsize and msize to fill slots in the format. */
+
+ quo = rows/8;
+ if (rows != quo*8) quo++;
+ i = quo*columns;
+ lsize += quo*columns;
+ quo = columns/8;
+ if (columns != quo*8) quo++;
+ psize += quo*rows;
+ if (i > quo*rows) msize += i; else msize += quo*rows;
+
+/* Now do the actual copy. We have to ensure that the rasters are
+word-aligned in the font load (where one word = 2 bytes, of course). */
+
+ if (lnf[def_start+16] % 2 == 0) len = quo*rows; else len = i;
+ if (read_nft_with_retry(&lnf[def_start+24],nftlen+len) != 0)
+ return(1);
+ lcy.l = def_start;
+ if (to <= leftlast) i = to-leftfirst; else i = to-rightfirst;
+ copy_to_lnf(lnf_chardir+4*i);
+ ras_len += len+24;
+ ras_len_added += len+24;
+ if (ras_len % 2 != 0) {
+ lnf[ras_beg+ras_len] = 0;
+ ras_len++;
+ ras_len_added++;
+ }
+ return(0);
+
+}
+
+int read_nft_with_retry(where,upto)
+long upto;
+char *where;
+{
+ long i,target;
+ int l;
+
+ i = 0;
+ while (nftlen < upto) {
+ target = upto-nftlen;
+ l = read(nftf,&where[i],target);
+ if (l <= 0) {
+ printf("\n LN03 font file bad, using blanks");
+ return(1);
+ }
+ nftlen += l;
+ i += l;
+ }
+ return(0);
+}
+
+int read_nft_until(pos)
+long pos;
+{
+ char bit_bucket[512];
+ int l;
+ long target;
+
+ while (nftlen < pos) {
+ target = pos-nftlen;
+ if (target > 512) target = 512;
+ l = read(nftf,bit_bucket,target);
+ if (l <= 0) {
+ printf("\n LN03 font file bad, using blanks");
+ return(1);
+ }
+ nftlen += l;
+ }
+ return(0);
+}
+
+GLOBAL unsigned char preline[96];
+
+/* write_lnf performs the last fixups to the LN03 font buffer and dumps it,
+sixelized, into the output file. */
+
+int write_lnf (){
+
+ long i,j,k,rem,quo,ma;
+
+/* We now have to fix a number of slots: size of file, length of rasters,
+final 'FONT', psize, lsize, msize. */
+
+ lcy.l = ras_beg+ras_len+8;
+ copy_to_lnf(0);
+ copy_to_lnf(lcy.l-8);
+ lnf[lcy.l-4] = 'F';
+ lnf[lcy.l-3] = 'O';
+ lnf[lcy.l-2] = 'N';
+ lnf[lcy.l-1] = 'T';
+
+/* Clear out remaining bytes up to 96 more. */
+
+ j = 96*((lcy.l+95)/96);
+ for (i=lcy.l; i<j; i++) lnf[i] = 0;
+
+/* Length of rasters */
+
+#define fnt__l_char_definitions_length 156
+
+ lcy.l = ras_len;
+ copy_to_lnf(fnt__l_char_definitions_length);
+
+#define fnt__l_portrait_byte_count 228
+#define fnt__l_landscape_byte_count 232
+#define fnt__l_mixed_byte_count 236
+
+ lcy.l = psize;
+ copy_to_lnf(fnt__l_portrait_byte_count);
+
+ lcy.l = lsize;
+ copy_to_lnf(fnt__l_landscape_byte_count);
+
+ lcy.l = msize;
+ copy_to_lnf(fnt__l_mixed_byte_count);
+
+/* Now sixelize and write the contents of LNF. */
+
+ sixelize_and_write(ras_beg+ras_len+8);
+ return(0);
+}
+
+int sixelize_and_write(howmuch)
+int howmuch;
+{
+ int quo,i,j;
+
+ quo = howmuch/96;
+ if (howmuch > quo*96) quo++;
+
+ for (i=0; i<quo; i++) {
+ for (j=0; j<96; j++)
+ preline[j] = lnf[96*i+j];
+ write_preline();
+ }
+
+}
+
+int write_preline() {
+
+ char sixel_line[129];
+ int i,j,ix,pllen;
+ unsigned v,w;
+
+ pllen = 96;
+ ix = 0;
+ sixel_line[128] = '\0';
+ for (i=0; i<128; i++) sixel_line[i] = '?';
+ for (i=0; i<pllen; i += 3) {
+ v = preline[i];
+ w = v>>2;
+ sixel_line[ix] = 63+w;
+ ix++;
+ w = (v&3)<<4;
+ v = preline[i+1];
+ w |= v>>4;
+ sixel_line[ix] = 63+w;
+ ix++;
+ w = (v&15)<<2;
+ v = preline[i+2];
+ w |= v>>6;
+ sixel_line[ix] = 63+w;
+ ix++;
+ w = v&63;
+ sixel_line[ix] = 63+w;
+ ix++;
+ }
+ fprintf(outfile,"\n%s",sixel_line);
+}
+
+/* Initializes the LN03 font buffer. */
+
+int initialize_lnf(lnfno)
+int lnfno;
+{
+ int i,j;
+
+/* The following array holds reasonable values for bytes 0-479 of an LN03
+format font. These bytes were copied from a font load which the LN03 was
+known to accept. The font loads generated by this program are initialized
+using these values. Some of them are overwritten later, however. */
+
+ static char good_opening[512] = {
+ 104,38,0,0,70,79,78,84,
+ 1,0,0,0,31,0,0,0,
+ 20,0,0,0,85,48,48,48,
+ 48,48,48,48,48,50,83,75,
+ 48,48,71,71,48,48,48,49,
+ 85,90,90,90,90,48,50,70,
+ 48,48,48,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 181,7,9,0,11,0,14,0,
+ 0,0,0,0,104,0,0,0,
+ 252,0,0,0,124,0,0,0,
+ 100,1,0,0,120,1,0,0,
+ 224,1,0,0,4,0,0,0,
+ 88,3,0,0,0,0,0,0,
+ 92,3,0,0,48,0,0,0,
+ 92,3,0,0,0,0,0,0,
+ 140,3,0,0,212,34,0,0,
+ 140,3,0,0,33,0,0,0,
+ 126,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 32,0,0,0,168,0,0,0,
+ 16,0,0,0,94,0,0,0,
+ 0,0,0,0,94,0,0,0,
+ 0,0,0,0,94,0,0,0,
+ 0,0,0,0,236,25,0,0,
+ 54,25,0,0,14,27,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,2,0,0,0,
+ 7,0,0,0,92,3,0,0,
+ 7,0,0,0,99,3,0,0,
+ 16,0,0,0,106,3,0,0,
+ 16,0,0,0,122,3,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 10,0,0,0,244,1,0,0,
+ 0,0,24,0,16,0,0,0,
+ 16,0,0,0,1,0,1,0,
+ 1,0,1,0,0,0,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 30,0,0,0,20,0,0,0,
+ 196,255,255,255,20,0,0,0,
+ 106,255,255,255,20,0,0,0,
+ 0,0,1,0,0,0,30,0,
+ 166,255,255,255,0,0,0,0,
+ 40,0,0,0,0,0,0,0,
+ 60,0,0,0,240,0,0,0,
+ 60,0,0,0,100,0,0,0,
+ 240,0,0,0,120,0,0,0,
+ 40,0,0,0,120,0,0,0,
+ 96,255,255,255,136,255,255,255,
+ 186,255,255,255,240,0,0,0,
+ 76,255,255,255,60,0,0,0,
+ 160,0,0,0,120,0,0,0,
+ 20,0,0,0,20,0,0,0,
+ 140,3,0,0,194,3,0,0,
+ 244,3,0,0,160,4,0,0,
+ 254,4,0,0,162,5,0,0,
+ 46,6,0,0,84,6,0,0};
+ int pool_beg;
+
+/* The character directory always begins at position 480 in the Common
+Font File Format. */
+
+ lnf_chardir = 480;
+ ras_len = 0;
+ psize = 0;
+ lsize = 0;
+ msize = 0;
+
+/* Copy the good values into the lnf array */
+
+ for (i=0; i<480; i++)
+ lnf[i] = good_opening[i];
+
+/* Set the last character if necessary */
+
+#define fnt__l_first_character 164
+
+ if (lastch[lnfno] < leftlast && !using_r)
+ lnf[fnt__l_first_character+4] = lastch[lnfno];
+ if (using_r)
+ lnf[fnt__l_first_character+4] = lastch[lnfno]-rightfirst+
+ leftfirst;
+
+/* Set the character counts */
+
+#define fnt__l_infile_locators 204
+#define fnt__l_character_definitions 212
+#define fnt__l_raster_count 220
+
+ i = lnf[fnt__l_first_character+4]-
+ lnf[fnt__l_first_character]+1;
+ ras_beg = lnf_chardir + 4*i + 4 + 48;
+ lnf[fnt__l_infile_locators] = i;
+ lnf[fnt__l_character_definitions] = i;
+ lnf[fnt__l_raster_count] = i;
+ lnf[ras_beg-52] = lnf[ras_beg-51] = lnf[ras_beg-50] =
+ lnf[ras_beg-49] = 0;
+
+/* Set the font file id. This id is a 31-byte string. We make it depend on
+the lnfno number, and on whether this is a left or right font.
+Specifically, the first seven bytes are U0000nn where nn is lnfno possibly
+with a leading zero. The character set part of the ID is 1O if using_r,
+otherwise the default from good_opening. */
+
+#define fnt__t_font_file_id 20
+
+ lnf[fnt__t_font_file_id+5] = lnfno/10+'0';
+ lnf[fnt__t_font_file_id+6] = lnfno % 10 + '0';
+ if (using_r) lnf[fnt__t_font_file_id+20] = 'O';
+
+/* We now have to set some fields in the font format that are pointers to
+where other fields begin. These pointers depend on the number of glyphs we
+are placing in the font file. */
+
+#define fnt__a_subset_tables 128
+
+ lcy.l = lnf_chardir+4*i;
+ copy_to_lnf(fnt__a_subset_tables);
+
+ lcy.l = lcy.l+4;
+ copy_to_lnf(fnt__a_subset_tables+8);
+ copy_to_lnf(fnt__a_subset_tables+16);
+
+ lcy.l = lcy.l+48;
+ copy_to_lnf(fnt__a_subset_tables+24);
+
+#define fnt__a_char_definitions 160
+
+ copy_to_lnf(fnt__a_char_definitions);
+
+/* Set up the string pool region of the font load (48 bytes). The only
+tricky part here is the character set designator at the very beginning of
+the pool. Left fonts use one designator, right fonts another. [[More
+explanation is needed.]] */
+
+ pool_beg = ras_beg-48;
+
+ lnf[pool_beg] = '0';
+ lnf[pool_beg+1] = using_r ? '<':'B';
+ lnf[pool_beg+2] = '\011'; /* ascii tab */
+ lnf[pool_beg+3] = 'Z';
+ lnf[pool_beg+4] = 'Z';
+ lnf[pool_beg+5] = 'Z';
+ lnf[pool_beg+6] = 'Z';
+
+/* For reasons that are beyond my comprehension, the Common Font File
+Format requires us to copy the first seven characters of the font file id
+into one piece of the string pool, and the first sixteen into another
+place. */
+
+ for (i=1; i<8; i++)
+ lnf[pool_beg+7+i-1] = lnf[fnt__t_font_file_id+i-1];
+ for (i=1; i<17; i++)
+ lnf[pool_beg+7+7+i-1] = ' ';
+ for (i=1; i<17; i++)
+ lnf[pool_beg+7+7+16+i-1] = lnf[fnt__t_font_file_id+i-1];
+ lnf[pool_beg+46] = lnf[pool_beg+47] = 0;
+
+/* Now make string descriptors point into the string pool. */
+
+#define fnt__a_char_set 260
+#define fnt__a_family_id 268
+#define fnt__a_family_name 276
+#define fnt__a_font_id 284
+
+ lcy.l = pool_beg;
+ copy_to_lnf(fnt__a_char_set);
+ lcy.l = pool_beg+7;
+ copy_to_lnf(fnt__a_family_id);
+ lcy.l = pool_beg+7+7;
+ copy_to_lnf(fnt__a_family_name);
+ lcy.l = pool_beg+7+7+16;
+ copy_to_lnf(fnt__a_font_id);
+
+/* Mercifully, all remaining font file slots that we can fill now are
+already good as received from good_opening. */
+
+}