#ifndef lint static char sccsid[] = "@(#)rdfont.c 9.2 88/01/19 Copyright 1984 Sun Micro"; #endif /* * Copyright (c) 1984 by Sun Microsystems, Inc. */ /*- Routines for reading in fonts rdfont.c, Tue May 21 15:27:56 1985 James Gosling, Sun Microsystems */ #include #include #include #ifdef REF #include #endif #include #include #include "fract.h" #include "font.h" #include "cmufont.h" char *read_whole_file(); int file_size; struct font * cst_readfont(name) char *name; { int fd = open(name, 0); char buf[300]; register char *fontfile; if (fd < 0) { static char *fontpath; register char *s; if (fontpath == 0) { fontpath = (char *) getenv("FONTPATH"); if (fontpath == 0) fontpath = "/usr/local/lib/fonts:/usr/lib/fonts/fixedwidthfonts"; } for (s = fontpath; *s;) { register char *d; for (d = s; *d && *d != ':'; d++); if (d == s) strcpy(buf, name); else sprintf(buf, "%.*s/%s", d-s, s, name); if ((fd = open(buf, 0)) >= 0) { name = buf; break; } if (*d==0) break; s = d+1; } if (fd < 0) return 0; } fontfile = read_whole_file(fd); close(fd); if (fontfile == 0) return 0; #define H ((struct header *) fontfile) #define disp ((struct dispatch *)(fontfile+sizeof(struct header))) if (H->magic == VFONT_MAGIC) { register struct font *f; register struct glyph *i; register struct dispatch *dp; register c; int size; int fontheight; size = 0; for (c = 0; c < 256; c++) { dp = &disp[c]; if (dp->nbytes > 0) size += (dp->up + dp->down) * (((dp->left + dp->right + 15) >> 4) << 1); } f = (struct font *) snoopalloc("rdfont.c", sizeof(struct font) + 256 * (sizeof(struct wglyph) + sizeof(struct glyph)) + size); i = (struct glyph *) & f->glyphs[256]; f->left_to_right = 1; f->narrow = 1; f->type = LRbitmapFont; f->encoding = ASCIIencoding; f->printermatched = 0; fontheight = H->maxy; { char newname[100]; register char *s, *d; d = name; s = name; while (*d) if (*d++ == '/') s = d; d = newname; while (*d++ = *s++); d--; if (strncmp(d - 6, ".vfont", 6) == 0) d -= 6; if (isdigit(d[-1])) { int newheight; while (isdigit(d[-1])) d--; if ((newheight = atoi(d)) > 0) fontheight = newheight; } if (d[-1] == '.') d--; if (d[-2] == '.') { d -= 2; switch (d[1]) { case 'b': s = "-Bold"; break; case 'i': s = "-Italic"; break; default: s = ""; break; } while (*d++ = *s++); } if (islower(newname[0])) newname[0] += 'A' - 'a'; f->name = (char *) snoopalloc("rdfont.c", strlen(newname) + 1); strcpy(f->name, newname); } f->comment = "Originally a BSD vfont."; f->matrix[0][0] = fracti(fontheight); f->matrix[0][1] = 0; f->matrix[1][0] = 0; f->matrix[1][1] = f->matrix[0][0]; f->nglyphs = 0; for (c = 0; c < 256; c++) { register struct wglyph *wg = &f->glyphs[c]; dp = &disp[c]; if (dp->nbytes > 0 /* && c >= 32 */) { int rowws = ((dp->left + dp->right + 15) >> 4); int size = rowws * 2 * (dp->up + dp->down); wg->glyph = i; i->length = size + sizeof(struct glyph); wg->width.x = fracti(dp->width); wg->width.y = 0; i->origin.x = dp->left; i->origin.y = dp->up; i->size.x = dp->left + dp->right; i->size.y = dp->up + dp->down; /* * vfont format rounds bitmap rows to a multiple of 8 * bits; we need them rounded to a multiple of 16 bits */ if (size != dp->nbytes) { register k; int rowbs = (dp->left + dp->right + 7) >> 3; bzero(((struct generic_glyph *) i)->bits, rowws * 2 * (k = dp->up + dp->down)); while (--k >= 0) bcopy(fontfile + dp->addr + (sizeof(struct header) + 256 * sizeof(struct dispatch)) + k * rowbs, ((struct generic_glyph *) i)->bits + k * rowws, rowbs); } else bcopy(fontfile + dp->addr + (sizeof(struct header) + 256 * sizeof(struct dispatch)), ((struct generic_glyph *) i)->bits, dp->nbytes); /* * increment i by the size of struct glyph plus size */ i = (struct glyph *) ((int) i + (size + sizeof(struct glyph))); f->nglyphs = c + 1; } else f->glyphs[c].glyph = 0; } trim_font(f); pst_compute_font_properties(f); return f; #undef H #undef disp } else if (FoldedPrefixMatch(fontfile, "startfontmetrics")) return (struct font *) cst_readfontmetrics(fontfile, file_size, name); else if (FoldedPrefixMatch(fontfile, "startfont")) { register struct font *f = (struct font *) cst_readadobefont(fontfile, file_size, name); pst_compute_font_properties(f); return f; } else if (((struct font *) fontfile)->u.magic == NEW_FONT_MAGIC) return (struct font *) unpackbfont(fontfile); else if (((struct cmufont *) fontfile)->magic == CMUFONTMAGIC) { register struct font *f = (struct font *) cst_readcmufont(fontfile); pst_compute_font_properties(f); return f; } else { fprintf(stderr, "%s: not a valid font file\n", buf); return 0; } } static trim_font(f) register struct font *f; { register i; if (f->type == PrinterWidthFont) return; for (i = 0; i < f->nglyphs; i++) { register struct glyph *p = f->glyphs[i].glyph; register unsigned short *b; register size, delta; if (p == 0) continue; if (p->size.x > 16) continue; b = ((struct generic_glyph *) p)->bits; size = p->size.y; delta = 0; while (--size >= 0 && *b++ == 0) delta++; if (size < 0) { if (i != ' ') f->glyphs[i].glyph = 0; else { p->size.y = 0, p->size.x = 0, p->origin.x = 0, p->origin.y = 0; p->length = sizeof(struct glyph); } continue; } if (delta > 0) { b = ((struct generic_glyph *) p)->bits; p->size.y -= delta; p->origin.y -= delta; while (size >= 0) { b[0] = b[delta]; b++; size--; } while (--delta >= 0) *b++ = 0; } b = ((struct generic_glyph *) p)->bits; size = p->size.y; delta = 0; while (--size >= 0) { delta++; if (*b++) { p->size.y = delta; p->length = delta * sizeof(short) + sizeof(struct glyph); } } b = ((struct generic_glyph *) p)->bits; size = p->size.y; delta = 0; while (--size >= 0) delta |= *b++; { register shift = 0; while ((delta & (1 << 15)) == 0) { shift++; delta <<= 1; } if (shift) { p->size.x -= shift; p->origin.x -= shift; b = ((struct generic_glyph *) p)->bits; size = p->size.y; while (--size >= 0) { *b = *b << shift; b++; } } shift = 0; while (((short) delta) != 0) { delta <<= 1; shift++; } p->size.x = shift; } } } print_font(f, level) register struct font *f; { if (f == 0) { printf("Font NIL\n"); return; } printf("Font %s(%g,%g,%g,%g)", f->name, floatfr(f->matrix[0][0]), floatfr(f->matrix[0][1]), floatfr(f->matrix[1][0]), floatfr(f->matrix[1][1])); printf(" %s pitch", f->fixed_width ? "fixed" : "variable"); if (f->left_to_right) printf(", left_to_right"); if (f->narrow) printf(", narrow"); switch (f->encoding) { case ASCIIencoding: printf(", ASCII encoding"); break; case AdobeEncoding: printf(", Adobe encoding"); break; case JISC6226Encoding: printf(", JISC6226 encoding"); break; case CyrillicEncoding: printf(", Cyrillic encoding"); break; case HangulEncoding: printf(", Hangul encoding"); break; case DevenageriEncoding: printf(", Devenageri encoding"); break; }; switch (f->type) { case LRbitmapFont: printf(", LRbitmap format"); break; case WidthFont: printf(", Width format"); break; case PrinterWidthFont: printf(", PrinterWidth format"); break; case SplineFont: printf(", Spline format"); break; case VectorFont: printf(", Vector format"); break; }; printf(", %d glyphs\n", f->nglyphs); if (f->comment) printf("\t%s\n", f->comment); if (level > 1) { register i; if (f->type != PrinterWidthFont) for (i = 0; i < f->nglyphs; i++) { register struct wglyph *wp = &f->glyphs[i]; register struct glyph *p = wp->glyph; extern char *FontCharacterName(); if (p == 0) { if (wp->width.x != 0) { printf(040 < i && i < 0177 ? "'%c'" : "%03o", i); printf(": empty -> %2d,%2d\n", floorfr(wp->width.x), floorfr(wp->width.y)); } continue; } printf(040 < i && i < 0177 ? "%10s '%c'" : "%10s %03o", FontCharacterName(f, i), i); printf(": %2d,%2d @ %2d,%2d -> %2d,%2d\n", p->size.x, p->size.y, p->origin.x, p->origin.y, floorfr(wp->width.x), floorfr(wp->width.y)); if (level == 3) { register unsigned short *bits = ((struct generic_glyph *) p)->bits; register n = p->length - sizeof(struct glyph); putchar('\t'); while (n > 1) { printf("%5x", *bits++); n -= 2; } putchar('\n'); } if (level > 3) { register unsigned short *bits = ((struct generic_glyph *) p)->bits; register rows = p->size.y; while (--rows >= 0) { register col; int lcol = 0; for (col = 0; col < p->size.x; col++) #ifdef LITTLEENDIAN /* VAX, 386 */ if (bits[col >> 4] & (1 << (col & 15))) { #else /* 680x0 */ if (bits[col >> 4] & ((1 << 15) >> (col & 15))) { #endif while (lcol < col) putchar(' '), lcol++; putchar('*'); lcol++; } bits += (p->size.x + 15) >> 4; putchar('\n'); } } } else for (i = 0; i < f->nglyphs; i++) { register struct wglyph *wp = &f->glyphs[i]; if (wp->width.x != 0) { printf(040 < i && i < 0177 ? "'%c'" : "%03o", i); printf(": %.4g\n", floatfr(wp->width.x)); } } } } static char *whole_buf; static int whole_size; char * read_whole_file(fd) { struct stat st; if (fstat(fd, &st) < 0 || st.st_size <= 0) return 0; if (st.st_size > whole_size) { if (whole_size) free(whole_buf); whole_buf = (char *) snoopalloc("rdfont.c", whole_size = st.st_size); } if (read(fd, whole_buf, whole_size) != st.st_size) return 0; file_size = st.st_size; return whole_buf; } static FoldedPrefixMatch(s1,s2) register char *s1, *s2; { while (*s2) if (((*s2++ ^ *s1++) & 0337) != 0) return 0; return 1; }