/* * Copyright (c) 1987, 1989 University of Maryland * Department of Computer Science. All rights reserved. * Permission to copy for any purpose is hereby granted * so long as this copyright notice remains intact. * * The code in this file was partially derived from another version by * Tim Morgan at UCI. * * TODO: * test */ #ifndef lint static char rcsid[] = "$Header$"; #endif #include #include #include #include #include "types.h" #include "error.h" #include "font.h" #include "fio.h" /* * RST (Imagen's font format) font operations. */ static int rst_read(), rst_getgly(), rst_rasterise(); static void rst_freefont(); #ifdef UCI #define D 1.0 /* I think */ #else #define D 150.0 #endif struct fontops rstops = { "rst", 0, D, rst_read, rst_getgly, rst_rasterise, rst_freefont }; #undef D /* * Local info. */ #define FILEMARK_SIZE 8 /* header `file mark' bytes to skip */ /* * rc describes one RST character information block. */ struct rc { i16 rc_height; /* character height (pixels) */ i16 rc_width; /* character width (pixels) */ i16 rc_yoffset; /* Y offset of reference point */ i16 rc_xoffset; /* X offset of reference point */ i32 rc_rastoff; /* raster offset */ i32 rc_TFMwidth; /* TFM width */ }; /* * rst_details are the RST-specific font details. * * We keep track of the number of characters converted to internal * glyph form, and when all have been done, we discard the now- * useless details. */ struct rst_details { int rd_unconv; /* number of characters unconverted */ struct rc *rd_rc; /* `font directory' */ char *rd_ras; /* raster space, until converted */ long rd_rastbase; /* adjust rc_rastoff by rastbase */ }; /* * Get the rst_details from font f. */ #define ftord(f) ((struct rst_details *)(f)->f_details) extern errno; char *malloc(); long ftell(); /* * Read an RST file. */ static int rst_read(f, fd) struct font *f; int fd; { register struct rst_details *rd; register FILE *fp; register struct rc *rc; register int i; int saverr; long presize, diroff; i32 firstgly, lastgly; fp = NULL; if ((rd = (struct rst_details *)malloc(sizeof *rd)) == 0) goto fail; rd->rd_ras = 0; rd->rd_rc = 0; /* * Read the header. */ errno = 0; /* try to make errno meaningful */ if ((fp = fdopen(fd, "r")) == NULL) { if (errno == 0) errno = EMFILE; goto fail; } (void) fseek(fp, (long)FILEMARK_SIZE, 0); fGetWord(fp, presize); /* bytes in preamble (from FILEMARK_SIZE+2) */ presize += 2 + FILEMARK_SIZE; i = getc(fp); /* version */ if (i != 0) { error(0, 0, "Warning: strange RST version (%d) in \"%s\"", i, f->f_path); errno = EINVAL; goto fail; } fGet3Byte(fp, diroff); /* offset to glyph directory */ fGetWord(fp, firstgly); /* first glyph */ fGetWord(fp, lastgly); /* last glyph (inclusive) */ lastgly++; /* make it exclusive */ (void) GetLong(fp); /* mag */ fGetLong(fp, f->f_design_size); /* interline, interword, rotation, charadv, lineadv */ (void) fseek(fp, (long)(4 + 4 + 2 + 1 + 1), 1); fGetLong(fp, f->f_checksum); f->f_hppp = 0; /* ??? */ f->f_vppp = 0; /* * Read the glyph directory. */ i = lastgly - firstgly; rd->rd_rc = (struct rc *)malloc((unsigned) (i * sizeof(*rc))); if (rd->rd_rc == 0) goto fail; (void) fseek(fp, presize, 0); for (rc = rd->rd_rc; --i >= 0; rc++) { fGetWord(fp, rc->rc_height); fGetWord(fp, rc->rc_width); fGetWord(fp, rc->rc_yoffset); fGetWord(fp, rc->rc_xoffset); fGetLong(fp, rc->rc_TFMwidth); fGet3Byte(fp, rc->rc_rastoff); } /* * Set up the raster pointer (if we need rasters). */ if (f->f_flags & FF_RASTERS) { struct stat st; rd->rd_rastbase = ftell(fp); /* back to unbuffered I/O */ (void) fstat(fd, &st); i = st.st_size - presize - 15 * (lastgly - firstgly); if (i < 0) error(1, 0, "calculated raster size < 0 for \"%s\"", f->f_path); if (i != 0) { if ((rd->rd_ras = malloc((unsigned) i)) == 0) goto fail; (void) lseek(fd, rd->rd_rastbase, 0); if (read(fd, rd->rd_ras, i) != i) goto fail; } } f->f_details = (char *) rd; if (FontHasGlyphs(f, firstgly, lastgly)) goto fail; (void) fclose(fp); rd->rd_unconv = lastgly - firstgly; return (0); fail: saverr = errno; if (rd) { if (rd->rd_rc) free((char *)rd->rd_rc); if (rd->rd_ras) free(rd->rd_ras); free((char *) rd); } if (fp) (void) fclose(fp); else (void) close(fd); errno = saverr; return (-1); } /* * Obtain the specified range of glyphs. */ static int rst_getgly(f, l, h) register struct font *f; int l; register int h; { register struct glyph *g; register struct rc *rc; register int i; struct rst_details *rd; if ((rd = ftord(f)) == NULL) panic("rst_getgly"); /* * By definition, all glyphs are valid. Just copy the * RST information. */ for (rc = &rd->rd_rc[(i = l) - f->f_lowch]; i < h; i++, rc++) { g = f->f_gly[i]; g->g_flags = GF_VALID; g->g_height = rc->rc_height; g->g_width = rc->rc_width; g->g_yorigin = rc->rc_yoffset; g->g_xorigin = rc->rc_xoffset; g->g_rawtfmwidth = rc->rc_TFMwidth; } return (0); } /* * Obtain rasters for the specified glyphs. */ static int rst_rasterise(f, l, h) register struct font *f; int l; register int h; { register struct glyph *g; register struct rc *rc; register struct rst_details *rd; register int i; unsigned sz; if ((rd = ftord(f)) == NULL) panic("rst_rasterise details==0"); if (rd->rd_ras == NULL) panic("rst_rasterise rd_ras==NULL"); for (rc = &rd->rd_rc[(i = l) - f->f_lowch]; i < h; i++, rc++) { g = f->f_gly[i]; if (!HASRASTER(g)) continue; if (rc->rc_rastoff == 0) { error(1, 0, "bad RST glyph %d in \"%s\"", g->g_index, f->f_path); } else { sz = ((g->g_width + 7) >> 3) * g->g_height; if ((g->g_raster = malloc(sz)) == NULL) return (-1); /* ??? */ g->g_rotation = ROT_NORM; bcopy(rd->rd_ras + rc->rc_rastoff - rd->rd_rastbase, g->g_raster, sz); } } /* * If we have converted all the characters, dump the * pre-conversion rasters. In fact, dump everything. */ rd->rd_unconv -= h - l; if (rd->rd_unconv == 0) { free((char *)rd->rd_rc); free(rd->rd_ras); free((char *)rd); f->f_details = NULL; } return (0); } /* * Discard the font details. */ static void rst_freefont(f) struct font *f; { struct rst_details *rd; if ((rd = ftord(f)) != NULL) { free((char *)rd->rd_rc); free(rd->rd_ras); free((char *)rd); } }