diff options
Diffstat (limited to 'dviware/beebe/src/openfont.h')
-rw-r--r-- | dviware/beebe/src/openfont.h | 324 |
1 files changed, 324 insertions, 0 deletions
diff --git a/dviware/beebe/src/openfont.h b/dviware/beebe/src/openfont.h new file mode 100644 index 0000000000..ff785609dd --- /dev/null +++ b/dviware/beebe/src/openfont.h @@ -0,0 +1,324 @@ +/* -*-C-*- openfont.h */ +/*-->openfont*/ +/**********************************************************************/ +/****************************** openfont ******************************/ +/**********************************************************************/ + +void +openfont(fontname) +char *fontname; + +/*********************************************************************** + The original version of this DVI driver reopened the font file each + time the font changed, resulting in an enormous number of relatively + expensive file openings. This version keeps a cache of up to + MAXOPEN open files, so that when a font change is made, the file + pointer, fontfp, can usually be updated from the cache. When the + file is not found in the cache, it must be opened. In this case, + the next empty slot in the cache is assigned, or if the cache is + full, the least used font file is closed and its slot reassigned for + the new file. Identification of the least used file is based on the + counts of the number of times each file has been "opened" by this + routine. On return, the file pointer is always repositioned to the + beginning of the file. + + If the first open attempt fails, an attempt will be made to use a + substitute font, then neighboring magnifications (with the same font + name), or substitutes for them. +***********************************************************************/ + +{ + register INT16 i,j,k; /* loop indices */ + INT16 current; + INT16 least_used; + INT16 maxopen = MAXOPEN; + +#if OS_VAXVMS + long *jpi; +#endif + + struct font_entry *tfontptr; + char subfont[MAXFNAME]; + int submag; + char* filelist[MAXFORMATS]; /* pointers to templist[][] */ + char templist[MAXFORMATS][MAXFNAME]; + +#if VIRTUAL_FONTS + struct stat statbuf; /* so fstat() can get file size */ + char *p; +#endif + + if ((pfontptr != (struct font_entry *)NULL) && (pfontptr == fontptr)) + return; /* we need not have been called */ + + for (j = 0; j < MAXFORMATS; ++j) /* initialize fontlist pointers */ + filelist[j] = &templist[j][0]; + +#if IBM_PC_MICROSOFT + /* This code required rewriting to get around a fatal compiler + assertion error occasioned by the code in the #else part */ + for (current = 1; current <= nopen; ++current) + { + FILE* pfp; + + pfp = font_files[current].font_id; + if (pfp == fontptr->font_file_id) + break; + } +#else + for (current = 1; + (current <= nopen) && + (font_files[current].font_id != fontptr->font_file_id); + ++current) + ; /* try to find file in open list */ +#endif + + if (current <= nopen) /* file already open, lookup its id */ + fontfp = font_files[current].font_id; + else + { + /*************************************************************** + The file was not in list of open files. If the list is not + full, add it to the list; otherwise close the least-used file + and remove it from the font_entry containing it. Finally, open + the file, or its closest neighbor in the magnification family. + A warning is issued if no file can be opened. The caller can + then proceed with zero font metrics if desired. + ***************************************************************/ + +#if OS_VAXVMS + /*************************************************************** + VAX VMS has many user quotas, one of which is the maximum number + of files that can be open, which need have no relation to the + number that C permits. If we do not determine the limit at + run-time, the drivers may attempt to open too many files, and in + such a case, will fail. There are two relevant quotas, FILLM + (open file limit), and FILCNT (remaining open file quota). We + use the latter, and leave one available file for a possible + error log. + ***************************************************************/ + + jpi = (long*)getjpi(JPI$_FILCNT); + if (jpi == (long*)NULL) + maxopen = MAXOPEN; /* should never happen */ + else + maxopen = nopen - 1 + *jpi; + maxopen = MIN(maxopen,MAXOPEN); /* we have arrays of size MAXFONT */ + /* so do not exceed that limit */ +#endif /* OS_VAXVMS */ + + if (nopen < maxopen) /* just add it to list */ + current = ++nopen; + else /* list full -- find least used file, */ + { /* close it, and reuse slot for new file */ + least_used = 1; + for (i = 2; i <= maxopen; ++i) + if (font_files[least_used].use_count > + font_files[i].use_count) + least_used = i; + + fontfp = font_files[least_used].font_id; + tfontptr = hfontptr; + while (tfontptr != (struct font_entry*)NULL) + { /* remove file pointer from its font_entry */ + if (tfontptr->font_file_id == fontfp) + { + tfontptr->font_file_id = (FILE*)NULL; + break; + } + tfontptr = tfontptr->next; + } + +#if VIRTUAL_FONTS + if (virt_font && (fontfp != (FILE*)NULL)) + (void)virtfree(fontfp); +#endif + + (void)fclose(fontfp); + fontfp = (FILE*)NULL; + current = least_used; + } + (void)actfact(fontptr->font_mag); /* Get global mag_index */ + + fontfp = (FILE*)NULL; + + /*************************************************************** + Try the requested font, then any substitute font, then for each + neighboring magnification from nearest to furthest, try the + requested font, and then any substitute font. + ***************************************************************/ + + for (k = 0; (fontfp == (FILE*)NULL) && (k < MAGTABSIZE); ++k) + { /* loop over mag family */ + for (i = -k; (fontfp == (FILE*)NULL) && (i <= k); i += MAX(1,k+k)) + { /* try smaller, then larger */ + if (IN(0,mag_index+i,MAGTABSIZE-1)) + { + (void)fontfile(filelist, ((fontptr->a==0)?fontpath:""), + fontname, (int)MAGSIZE(mag_table[mag_index+i])); + for (j = 0; (j < MAXFORMATS) && *filelist[j]; ++j) + { + fontfp = FOPEN(filelist[j],RB_OPEN); + DEBUG_OPEN(fontfp,filelist[j],RB_OPEN); + if (fontfp != (FILE *)NULL) + { + strcpy(fontptr->name,filelist[j]); + break; + } + } + if ((k > 0) && (fontfp != (FILE*)NULL)) + { + (void)sprintf(message, + "Font file [%s [mag %d]] could not be opened.\n\ +---using nearest neighbor [%s [mag %d]] instead.", + fontname,(int)MAGSIZE(mag_table[mag_index]), + fontptr->name, + (int)MAGSIZE(mag_table[mag_index+i])); + (void)warning(message); + } + + if ((fontfp == (FILE*)NULL) && fontsub(subfont,&submag, + fontname,(int)MAGSIZE(mag_table[mag_index+i]))) + { + (void)fontfile(filelist,((fontptr->a==0)?fontpath:""), + subfont,(submag ? submag : + (int)MAGSIZE(mag_table[mag_index+i]))); + for (j = 0; (j < MAXFORMATS) && *filelist[j]; ++j) + { + fontfp = FOPEN(filelist[j],RB_OPEN); + DEBUG_OPEN(fontfp,filelist[j],RB_OPEN); + if (fontfp != (FILE *)NULL) + { + strcpy(fontptr->name,filelist[j]); + break; + } + } + + if (fontfp != (FILE*)NULL) + { + (void)sprintf(message, + "Substituting font file [%s [mag %d]] \ +by [%s [mag %d]]", + fontname,(int)MAGSIZE(mag_table[mag_index]), + fontptr->name, + (int)MAGSIZE(mag_table[mag_index+i])); + (void)warning(message); + } + } + } + } /* end for (i) -- loop over smaller and larger neighbors */ + } /* end for (k) -- loop over mag family */ + + if (fontfp == (FILE*)NULL) + { + --nopen; /* don't count this failed open */ + (void)sprintf(message,"Font file [%s [mag %d]] could not be \ +opened; %d font files are open\n\ +Proceeding with zero size characters for this font", + fontname,(int)MAGSIZE(mag_table[mag_index]),nopen); + (void)warning(message); + } + + font_files[current].font_id = fontfp; + font_files[current].use_count = 0; + +#if VIRTUAL_FONTS + /* + **************************************************************** + This code is implementation-dependent. On many C compilers, + FILE points to a struct of the form + + struct _iobuf { + char *_ptr; // pointer to next available char + int _cnt; // number of chars left in buffer + char *_base; // pointer to start of buffer + int _flag; // assorted flags + int _file; // file number handle + } + + To implement virtual fonts, we save the pointers in a private + global array, get the file size from fstat(), malloc() a buffer + for it, read the entire file in, and replace the pointers in the + FILE variable with ones for the new buffer. Just before the + file is closed, the space is freed and the old pointers are + restored. Although many C implementations use malloc() to get + the buffer space in the first place, which would make this + saving unnecessary, not all do; see the implementation given in + Kernighan and Ritchie "The C Programming Language", p. 168. + + In implementing this code on any new machine, the + implementations of fread(), read(), fseek(), and rewind() should + be checked to choose the most efficient one (e.g. one system + call for entire file read, and no double buffering), and make + sure that fseek() and rewind() do not unnecessarily discard + input buffer contents. fseek() and rewind() are defined in + terms of macros FSEEK() and REWIND() in machdefs.h to facilitate + replacement. + **************************************************************** + */ + if (virt_font) + { + virt_save[fileno(fontfp)].base = (char *)NULL; + (void)fstat(fileno(fontfp),&statbuf); /* get file size */ + p = (char *)MALLOC((int)statbuf.st_size); /* get file buffer */ + if (p != (char *)NULL) + { + if (READ(fileno(fontfp),p,(int)statbuf.st_size) + == (int)statbuf.st_size) + { /* read successful */ + virt_save[fileno(fontfp)].ptr = FILE_PTR(fontfp); + virt_save[fileno(fontfp)].cnt = FILE_CNT(fontfp); + virt_save[fileno(fontfp)].base = FILE_BASE(fontfp); + FILE_PTR(fontfp) = p; + FILE_BASE(fontfp) = p; + FILE_CNT(fontfp) = (int)statbuf.st_size; + } + else /* failure */ + { + (void)REWIND(fontfp); + (void)free(p); /* free dynamic buffer */ + } + } + if (DBGOPT(DBG_FONT_CACHE)) + { + (void)fprintf(stderr,"\nopenfont(): Font file %d [%s] ", + (int)fileno(fontfp),fontptr->name); + if (p == (char *)NULL) + (void)fprintf(stderr, + "cannot callocate buffer for entire file\n"); + else + (void)fprintf(stderr, + "buffer length 0x%x\told buffer at 0x%lx\t\ +new buffer at 0x%lx\n", + (int)statbuf.st_size, + (long)virt_save[fileno(fontfp)].base, + (long)FILE_BASE(fontfp)); + } + } +#endif + + } /* end if (file is in open list) */ + + pfontptr = fontptr; /* make previous = current font */ + fontptr->font_file_id = fontfp; /* set file identifier */ + font_files[current].use_count++; /* update reference count */ +} + +#if VIRTUAL_FONTS +void +virtfree(fp) /* free buffer space before close */ +FILE *fp; +{ + if (virt_font && (fp != (FILE*)NULL) && + (virt_save[fileno(fp)].base != (char *)NULL)) + { + (void)fflush(fp); + (void)free(FILE_BASE(fp)); + FILE_PTR(fp) = virt_save[fileno(fp)].ptr; + FILE_CNT(fp) = virt_save[fileno(fp)].cnt; + FILE_BASE(fp) = virt_save[fileno(fp)].base; + virt_save[fileno(fp)].base = (char *)NULL; + } +} +#endif + |