|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T f
Length: 20760 (0x5118) Types: TextFile Names: »fonts.c«
└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89 └─⟦this⟧ »./DVIware/crt-viewers/others/fonts.c«
/* * dvipage: DVI Previewer Program for Suns * * Neil Hunt (hunt@spar.slb.com) * * This program is based, in part, upon the program dvisun, * distributed by the UnixTeX group, extensively modified by * Neil Hunt at the Schlumberger Palo Alto Research Laboratories * of Schlumberger Technologies, Inc. * * Copyright (c) 1988 Schlumberger Technologies, Inc 1988. * Anyone can use this software in any manner they choose, * including modification and redistribution, provided they make * no charge for it, and these conditions remain unchanged. * * This program is distributed as is, with all faults (if any), and * without any warranty. No author or distributor accepts responsibility * to anyone for the consequences of using it, or for whether it serves any * particular purpose at all, or any other reason. * * $Log: fonts.c,v $ * Revision 1.1 88/11/28 18:40:54 hunt * Initial revision * * Stripped out of dvipage 1.4, * with additions from mitdrivers from TeX 1988 distribution tape. */ #include <stdio.h> #include <sys/param.h> /* For MAXPATHLEN */ #include <fcntl.h> #include <suntool/sunview.h> #include "dvipage.h" #include "dvi.h" forward FILE * open_font_file(); forward bool init_font_file(); forward bool read_font_char(); static int nopen = 0; /* number of open FNT files */ /* * get_font_def: * Read the font definitions as they are in the postamble of the DVI file. * Returns TRUE unless the document can not be processed further. */ bool get_font_def() { char *calloc (); unsigned char byte; while(((byte = get_unsigned(dvifp, 1)) >= FNT_DEF1) && (byte <= FNT_DEF4)) { switch (byte) { case FNT_DEF1: if(! read_font_def(get_unsigned(dvifp, 1))) return FALSE; break; case FNT_DEF2: if(! read_font_def(get_unsigned(dvifp, 2))) return FALSE; break; case FNT_DEF3: if(! read_font_def(get_unsigned(dvifp, 3))) return FALSE; break; case FNT_DEF4: if(! read_font_def(get_unsigned(dvifp, 4))) return FALSE; break; default: message( "%s: Bad dvi file: bad font specification.", filename); return FALSE; } } if(byte != POST_POST) { message( "%s: Bad dvi file: no postpostamble after fontdefs.", filename); return FALSE; } return TRUE; } /* * skip_font_def: * Ignore font definition when fonts have been read from the postamble. */ /* ARGSUSED */ void skip_font_def(k) int k; { int a, l; (void)get_unsigned(dvifp, 4); (void)get_unsigned(dvifp, 4); (void)get_unsigned(dvifp, 4); a = get_unsigned(dvifp, 1); l = get_unsigned(dvifp, 1); fseek(dvifp, (long)a+l, 1); } /* * read_font_def: * Reads font def, and attempts to open font file and read data. * Returns TRUE unless a fatal error has occurred so that * document processing cannot proceed. */ bool read_font_def(k) int k; { int i; struct char_entry *tcharptr; FILE *font_fp; /* * Allocate and link new font entry. */ if((fontptr = (struct font_entry *)calloc(1, sizeof(struct font_entry))) == NULL) { message( "Out of memory for font entries; try a larger machine."); return FALSE; } fontptr->next = hfontptr; hfontptr = fontptr; /* * Fill in new font entry. */ fontptr->font_file_fd = NULL; fontptr->k = k; fontptr->c = get_unsigned(dvifp, 4); /* checksum */ fontptr->s = get_unsigned(dvifp, 4); /* space size */ fontptr->d = get_unsigned(dvifp, 4); /* design size */ fontptr->a = get_unsigned(dvifp, 1); /* area length for font name */ fontptr->l = get_unsigned(dvifp, 1); /* device length */ fread(fontptr->n, 1, fontptr->a+fontptr->l, dvifp); fontptr->n[fontptr->a+fontptr->l] = '\0'; fontptr->font_space = fontptr->s/6; /* never used */ fontptr->font_gf_mag = (int)((actual_factor((int)(((float)fontptr->s/ (float)fontptr->d)*1000.0 + 0.5)) * #ifdef USEGLOBALMAG actual_factor(mag) * #endif (float)resolution) + 0.5); fontptr->font_pxl_mag = (int)((actual_factor((int)(((float)fontptr->s/ (float)fontptr->d)*1000.0 + 0.5)) * #ifdef USEGLOBALMAG actual_factor(mag) * #endif (float)resolution * 5.0) + 0.5); /* * Try to find the font file to match. */ if(! find_font_file(font_path, fontptr) || (font_fp = open_font_file(fontptr)) == NO_FILE) { message("Cant find or open font file \"%s\" .%dgf or .%dpxl", fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag); if(verbose & DEBUG_FONTS) fprintf(stderr, "Cant find font file %s %s .%dgf or .%dpxl\n", font_path, fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag); fontptr->font_file_fd = NO_FILE; fontptr->magnification = 0; fontptr->designsize = 0; for(i = 0; i < NFNTCHARS; i++) { tcharptr = &(fontptr->ch[i]); tcharptr->width = 0; tcharptr->height = 0; tcharptr->xOffset = 0; tcharptr->yOffset = 0; tcharptr->where.isloaded = FALSE; tcharptr->where.address.fileOffset = NONEXISTENT; tcharptr->tfmw = 0; } return TRUE; } else return init_font_file(font_fp, fontptr); } /* * open_font_file: * Called with fontptr; opens a file for this font. * May have to close another to do it. * Returns a FILE * pointer, or NO_FILE. */ FILE * open_font_file(fontptr) struct font_entry *fontptr; { register struct font_entry *tfontptr, *lufontptr; register int used; if(nopen >= MAXOPEN) { used = MAXINT; lufontptr = NULL; for(tfontptr = hfontptr; tfontptr; tfontptr = tfontptr->next) { if(tfontptr->font_file_fd == NO_FILE || tfontptr->font_file_fd == NULL || tfontptr == fontptr) continue; if(tfontptr->use_count < used) { used = tfontptr->use_count; lufontptr = tfontptr; } } if(lufontptr == NULL) { fprintf(stderr, "Cant have no least used font\n"); exit(1); } if(verbose & DEBUG_FONTS) fprintf(stderr, "Closing (%x) font '%s'\n", lufontptr->font_file_fd, lufontptr->name); fclose(lufontptr->font_file_fd); lufontptr->font_file_fd = NULL; --nopen; } /* * Open the file; close-on-exec. */ if((fontptr->font_file_fd = fopen(fontptr->name, "r")) == NULL) { message("Cant open font file %s", fontptr->name); fontptr->font_file_fd = NO_FILE; } else { if(verbose & DEBUG_FONTS) fprintf(stderr, "Opened (%x) font '%s'\n", fontptr->font_file_fd, fontptr->name); fcntl(fileno(fontptr->font_file_fd), F_SETFD, 1); nopen++; } return fontptr->font_file_fd; } /* * close_fonts: * Closes all the font files, and frees up all the memory. */ void close_fonts() { register struct font_entry *pf, *next; register struct pixrect *pr; register int i; for(pf = hfontptr; pf; pf = next) { if(verbose & DEBUG_FONTS) fprintf(stderr, "Freeing font %s\n", pf->name); /* * Close the file if still open. */ if(pf->font_file_fd != NO_FILE && pf->font_file_fd != NULL) { fclose(pf->font_file_fd); --nopen; } pf->font_file_fd = NULL; /* * Free the pixrects. */ for(i = 0; i < NFNTCHARS; i++) { if(pf->ch[i].where.isloaded == TRUE) { if(pr = pf->ch[i].where.address.pixrectptr) pr_destroy(pr); } } /* * Get the next. */ next = pf->next; free(pf); } hfontptr = NULL; fontptr = NULL; if(nopen != 0) { fprintf(stderr, "Mislaid some font files; cant happen\n"); exit(1); } } /* * load_char: * Reads in a character from the font file. * Returns TRUE unless document cannot be processed. */ bool load_char(fontptr, ptr) struct font_entry *fontptr; struct char_entry *ptr; { register FILE *font_fp; if(verbose & DEBUG_CHARS) fprintf(stderr, "Load char %d of font %s at offset %d\n", (ptr - &fontptr->ch[0]), fontptr->name, ptr->where.address.fileOffset); /* * If the font file is currently unopen, then open it. */ if((font_fp = fontptr->font_file_fd) == NULL) font_fp = open_font_file(fontptr); /* * If the font file is unavailable, forget it. */ if(font_fp == NO_FILE) { ptr->where.isloaded = TRUE; return TRUE; } /* * Read the font character. */ return read_font_char(font_fp, fontptr, ptr); } /* * Generic Font reading functions. * ============================== */ forward bool init_gf_font_file(); forward bool init_pxl_font_file(); forward bool read_gf_font_char(); forward bool read_pxl_font_char(); /* * init_font_file: * Reads general data from font file. * Returns TRUE unless processing cannot continue. */ bool init_font_file(font_fp, fontptr) FILE *font_fp; struct font_entry *fontptr; { switch(fontptr->type) { case TYPE_GF: return init_gf_font_file(font_fp, fontptr); case TYPE_PXL: return init_pxl_font_file(font_fp, fontptr); default: fprintf(stderr, "Unknown type of font file; cant happen\n"); exit(1); } } /* * read_font_char: * Reads character from font file. * Returns TRUE unless document cannot be processed. */ bool read_font_char(font_fp, fontptr, ptr) FILE *font_fp; struct font_entry *fontptr; struct char_entry *ptr; { switch(fontptr->type) { case TYPE_GF: return read_gf_font_char(font_fp, fontptr, ptr); case TYPE_PXL: return read_pxl_font_char(font_fp, fontptr, ptr); default: fprintf(stderr, "Unknown type of font file; cant happen\n"); exit(1); } } /* * GF font reading functions. * ========================== */ #define false 0 #define true 1 /* The following macros describe gf file format */ #define paint_0 0 #define last_paint 63 #define paint1 64 #define paint2 65 #define paint3 66 #define boc 67 #define boc1 68 #define eoc 69 #define skip0 70 #define skip1 71 #define skip2 72 #define skip3 73 #define new_row_0 74 #define last_new_row 238 #define xxx1 239 #define xxx2 240 #define xxx3 241 #define xxx4 242 #define yyy 243 #define no_op 244 #define char_loc 245 #define char_loc0 246 #define pre 247 #define post 248 #define postpost 249 #define undefined_cases 250: case 251: case 252: case 253: case 254: case 255 #define gf_version 131 /* * init_gf_font_file: * Reads font data from file. * If the file is unavailable, its fp is set to NO_FILE. * Returns TRUE unless processing cannot continue. */ bool init_gf_font_file(font_fp, fontptr) FILE *font_fp; struct font_entry *fontptr; { register int b, c; register struct char_entry *tcharptr; long checksum; /* should match TFM file and DVI file */ long hppp, vppp; /* horizontal and vertical pixels/point scaled * 1<<16 */ int font_min_m, font_max_m, font_min_n, font_max_n; int char_wd; /* character width in pixels, rounded if * necessary */ /* * Seek to the postamble part of the GF file. */ fseek(font_fp, -5L, 2); /* skip four 223's */ do { c = get_unsigned(font_fp, 1); fseek(font_fp, -2L, 1); } while(c == 223); if(c != gf_version) { message("Bad GF font version number (%d) in %s.", c, fontptr->name); fclose(fontptr->font_file_fd); fontptr->font_file_fd = NO_FILE; return TRUE; } fseek(font_fp, -3L, 1); /* back up to the pointer */ if(fseek(font_fp, (long)get_unsigned(font_fp, 4), 0) < 0 || get_unsigned(font_fp, 1) != post) { message("Bad GF font file format in %s.", fontptr->name); fclose(fontptr->font_file_fd); fontptr->font_file_fd = NO_FILE; return TRUE; } (void)get_unsigned(font_fp, 4); /* ignore back pointer to font-wide xxx * commands */ fontptr->designsize = get_unsigned(font_fp, 4); checksum = get_unsigned(font_fp, 4); hppp = get_unsigned(font_fp, 4); vppp = get_unsigned(font_fp, 4); font_min_m = get_unsigned(font_fp, 4); font_max_m = get_unsigned(font_fp, 4); font_min_n = get_unsigned(font_fp, 4); font_max_n = get_unsigned(font_fp, 4); if(verbose & DEBUG_FONTS) fprintf(stderr, "Initialising font %s\n", fontptr->name); for(tcharptr = &fontptr->ch[0]; tcharptr < &fontptr->ch[NFNTCHARS]; tcharptr++) { tcharptr->where.isloaded = FALSE; tcharptr->where.address.fileOffset = -1; tcharptr->tfmw = 0; } for(;;) { b = get_unsigned(font_fp, 1); c = get_unsigned(font_fp, 1); if(verbose & DEBUG_CHARS) fprintf(stderr, "Finding char %d type %d\n", c, b); if(b == char_loc0) char_wd = get_unsigned(font_fp, 1); else if(b == char_loc) { char_wd = (get_unsigned(font_fp, 4) + 0100000) >> 16; get_unsigned(font_fp, 4); /* skip dy */ } else break; tcharptr = &(fontptr->ch[c % NFNTCHARS]); tcharptr->tfmw = ((float)get_unsigned(font_fp, 4) * (float)fontptr->s) / (float)(1 << 20); tcharptr->where.address.fileOffset = get_unsigned(font_fp, 4); } if((fontptr->c != 0) && (checksum != 0) && (fontptr->c != checksum)) message("Bad font checksum %d != %d, font %s.", checksum, fontptr->c, fontptr->name); /* * Return leaving font file open for use. */ return TRUE; } /* * read_font_char: * Reads character from font file. * Returns TRUE unless document cannot be processed. */ bool read_gf_font_char(font_fp, fontptr, ptr) FILE *font_fp; struct font_entry *fontptr; register struct char_entry *ptr; { register int i, b, c; register int x, y; register struct pixrect *pr; int min_m, max_m, min_n, max_n; int bytes, lines, paint_switch; long backpointer; long charfam; if(verbose & DEBUG_CHARS) fprintf(stderr, "Reading char %d of font %s\n", (ptr - &fontptr->ch[0]), fontptr->name); /* * Seek to start of char. */ fseek(font_fp, (long)ptr->where.address.fileOffset, 0); /* * Sync with char */ do { switch(i = get_unsigned(font_fp, 1)) { case yyy: (void)get_unsigned(font_fp, 1); /* FALLTHROUGH */ case paint3: case skip3: (void)get_unsigned(font_fp, 1); /* FALLTHROUGH */ case paint2: case skip2: (void)get_unsigned(font_fp, 1); /* FALLTHROUGH */ case paint1: case skip1: (void)get_unsigned(font_fp, 1); break; case boc: case boc1: break; case pre: if((c = get_unsigned(font_fp, 1)) != gf_version) { message( "Bad GF font version number (%d); font %s.", c, fontptr->name); return TRUE; } fseek(font_fp, (long)get_unsigned(font_fp, 1), 1); break; case xxx1: fseek(font_fp, (long)get_unsigned(font_fp, 1), 1); break; case xxx2: fseek(font_fp, (long)get_unsigned(font_fp, 2), 1); break; case xxx3: fseek(font_fp, (long)get_unsigned(font_fp, 3), 1); break; case xxx4: fseek(font_fp, (long)get_unsigned(font_fp, 4), 1); break; case post: if(verbose & DEBUG_FONTS) fprintf(stderr, "gettochar: found POST\n"); return TRUE; case char_loc: case char_loc0: case postpost: case undefined_cases: message( "Bad GF font file format (%d); font %s.", i, fontptr->name); return TRUE; default: /* do nothing */ ; break; } if(i != boc && i != boc1 && verbose & DEBUG_FONTS) fprintf(stderr, "gettochar iterates with %d\n", i); } while(i != boc && i != boc1); /* * Read character code and raster sizes. */ switch(i) { case boc: c = get_unsigned(font_fp, 4); backpointer = get_unsigned(font_fp, 4); min_m = get_unsigned(font_fp, 4); max_m = get_unsigned(font_fp, 4); min_n = get_unsigned(font_fp, 4); max_n = get_unsigned(font_fp, 4); charfam = c < 0 ? -((-c) >> 8) : c >> 8; break; case boc1: c = get_unsigned(font_fp, 1); x = get_unsigned(font_fp, 1); /* del_m */ max_m = get_unsigned(font_fp, 1); min_m = max_m - x; x = get_unsigned(font_fp, 1); /* del_n */ max_n = get_unsigned(font_fp, 1); min_n = max_n - x; break; default: fprintf(stderr, "Font BOC code has corrupted in memory; cant happen.\n"); exit(1); } ptr->width = max_m - min_m + 1; ptr->height = max_n - min_n + 1; ptr->xOffset = -min_m; ptr->yOffset = max_n; /* * Create Pixrect for char. * Clear to zero. */ pr = mem_create(ptr->width, ptr->height, 1); ptr->where.address.pixrectptr = pr; pr_rop(pr, 0, 0, ptr->width, ptr->height, PIX_SRC | PIX_COLOR(0), NULL, 0, 0); #ifdef NEVER pr_rop(pr, 0, 0, ptr->width, ptr->height, PIX_SRC | PIX_COLOR(1), NULL, 0, 0); pr_rop(pr, 1, 1, ptr->width-2, ptr->height-2, PIX_SRC | PIX_COLOR(0), NULL, 0, 0); #endif NEVER x = 0; y = 0; paint_switch = 0; for(;;) { switch(b = get_unsigned(font_fp, 1)) { case paint1: bytes = get_unsigned(font_fp, 1); goto paint; case paint2: bytes = get_unsigned(font_fp, 2); goto paint; case paint3: bytes = get_unsigned(font_fp, 3); goto paint; case skip0: lines = 0; goto skip; case skip1: lines = get_unsigned(font_fp, 1); goto skip; case skip2: lines = get_unsigned(font_fp, 2); goto skip; case skip3: lines = get_unsigned(font_fp, 3); goto skip; case xxx1: fseek(font_fp, (long)get_unsigned(font_fp, 1), 1); continue; case xxx2: fseek(font_fp, (long)get_unsigned(font_fp, 2), 1); continue; case xxx3: fseek(font_fp, (long)get_unsigned(font_fp, 3), 1); continue; case xxx4: fseek(font_fp, (long)get_unsigned(font_fp, 4), 1); continue; case yyy: get_unsigned(font_fp, 4); continue; case no_op: continue; case eoc: ptr->where.isloaded = TRUE; return TRUE; default: if(b >= paint_0 && b <= last_paint) { bytes = b - paint_0; paint:; /* * Paint the specified number of bytes black * or white. * Toggle the paint colour. * Advance the current position. */ if(verbose & DEBUG_CHARS) fprintf(stderr, " Paint %d line %d, %d for %d\n", paint_switch, y, x, bytes); if(bytes > 0 && paint_switch) pr_rop(pr, x, y, bytes, 1, PIX_SRC | PIX_COLOR(1), NULL, 0, 0); paint_switch = ! paint_switch; x += bytes; continue; } else if(b >= new_row_0 && b <= last_new_row) { /* * Special shortcut; skip to new row, * and paint some white bytes. * Leave switch ready for next black bytes. */ y++; x = b - new_row_0; paint_switch = 1; if(verbose & DEBUG_CHARS) fprintf(stderr, " Jump to line %d, paint white to %d\n", y, x); continue; } else { message( "Bad GF file format code %d; char %d font %s.", b, (ptr - &fontptr->ch[0]), fontptr->name); return TRUE; } skip:; /* * Skip to the start of the line.th next line. * Start at beginnning of line, ready to paint white. */ y += lines + 1; x = 0; paint_switch = 0; if(verbose & DEBUG_CHARS) fprintf(stderr, " Jump to line %d at start\n", y); continue; } } } /* * PXL font reading functions. * ========================== */ #define NPXLCHARS 128 /* * init_pxl_font_file: * Reads font data from file. * If the file is unavailable, its fp is set to NO_FILE. * Returns TRUE unless processing cannot continue. */ bool init_pxl_font_file(font_fp, fontptr) FILE *font_fp; struct font_entry *fontptr; { int t, i; register struct char_entry *tcharptr; /* * Read the PXL file */ if((t = get_unsigned(font_fp, 4)) != PXLID) { message("Bad font file version %d; font %s.", t, fontptr->name); fclose(fontptr->font_file_fd); fontptr->font_file_fd = NO_FILE; return TRUE; } fseek(font_fp, -20L, 2); t = get_unsigned(font_fp, 4); if((fontptr->c != 0) && (t != 0) && (fontptr->c != t)) message("Bad font checksum %d != %d; font %s.", t, fontptr->c, fontptr->name); fontptr->magnification = get_unsigned(font_fp, 4); fontptr->designsize = get_unsigned(font_fp, 4); fseek(font_fp, (long)get_unsigned(font_fp, 4) * 4, 0); for(i = 0; i < NPXLCHARS; i++) { tcharptr = &(fontptr->ch[i]); tcharptr->width = get_unsigned(font_fp, 2); tcharptr->height = get_unsigned(font_fp, 2); tcharptr->xOffset= get_signed(font_fp, 2); tcharptr->yOffset = get_signed(font_fp, 2); tcharptr->where.isloaded = FALSE; tcharptr->where.address.fileOffset = get_unsigned(font_fp, 4) * 4; tcharptr->tfmw = ((float)get_unsigned(font_fp, 4)*(float)fontptr->s) / (float)(1<<20); } /* * Return leaving font file open for access. */ return TRUE; } /* * read_font_char: * Reads character from font file. * Returns TRUE unless document cannot be processed. */ /* ARGSUSED */ bool read_pxl_font_char(font_fp, fontptr, ptr) FILE *font_fp; struct font_entry *fontptr; register struct char_entry *ptr; { register struct pixrect *pr; register int nshorts, i, col, nints; register short *dp, *sp; int buf[8]; /* * Seek to start of char. */ fseek(font_fp, (long)ptr->where.address.fileOffset, 0); /* * Create a mem pixrect. * Read the char. */ pr = mem_create(ptr->width, ptr->height, 1); nshorts = mpr_mdlinebytes(pr) >> 1; nints = (ptr->width + 31) >> 5; dp = mpr_d(pr)->md_image; for(col = 0; col < ptr->height; col++) { fread(buf, 4, nints, font_fp); sp = (short *) &buf[0]; for(i = nshorts; i > 0; i--) *dp++ = *sp++; } ptr->where.address.pixrectptr = pr; ptr->where.isloaded = TRUE; return TRUE; }