/* * Copyright (c) 1987 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. */ #ifndef lint static char rcsid[] = "$Header: font_subr.c,v 2.4 87/06/16 18:28:02 chris Exp $"; #endif /* * Subroutines common to all fonts. */ #include "font.h" static struct glyph *freeglyphs; char *malloc(); extern errno; /* * Set up the font structures to note that a font has glyphs in * the half-open interval [low, high). * * SHOULD I ALLOW ADDITIONS TO THE RANGE VIA SUBSEQUENT CALLS TO * FontHasGlyphs? */ FontHasGlyphs(f, low, high) register struct font *f; register int low, high; { register struct glyph **gp; /* record bounds */ f->f_lowch = low; f->f_highch = high; /* * Allocate space for all the glyph pointers, and set * them all to NULL. */ if (low >= high) /* no glyphs */ gp = NULL; else { gp = (struct glyph **) malloc((unsigned) (high - low) * sizeof (*gp)); if (gp == NULL) return (-1); } f->f_glybase = gp; f->f_gly = gp - low; while (++low <= high) *gp++ = NULL; return (0); } /* * AllocGlyph allocates a new glyph. ReleaseGlyph puts one onto the free * list. We maintain a local list of free glyphs. */ #define ReleaseGlyph(g) \ ((g)->g_un.g_next = freeglyphs, freeglyphs = (g)) static struct glyph * AllocGlyph(n) int n; { register struct glyph *g; register int i; if ((g = freeglyphs) == NULL) { g = (struct glyph *) malloc((unsigned) (128 * sizeof (*g))); if (g == NULL) error(1, errno, "out of glyph memory"); g += (i = 128); while (--i >= 0) { g--; ReleaseGlyph(g); } } freeglyphs = g->g_un.g_next; g->g_flags = 0; g->g_raster = NULL; g->g_index = n; return (g); } /* * Free one glyph. */ void FreeGlyph(f, n) struct font *f; register int n; { register struct glyph *g; if (n < f->f_lowch || n >= f->f_highch) return; #ifdef notdef (*f->f_ops->fo_freegly)(f, n, n); #endif if ((g = f->f_gly[n]) == NULL) return; if (g->g_raster != NULL) free(g->g_raster); ReleaseGlyph(g); } /* * Free a font. */ void FreeFont(f) register struct font *f; { register struct glyph *g; register int i; #ifdef notdef (*f->f_ops->fo_freegly)(f, f->f_lowch, f->f_highch); #endif for (i = f->f_lowch; i < f->f_highch; i++) { if ((g = f->f_gly[i]) == NULL) continue; if (g->g_raster != NULL) free(g->g_raster); ReleaseGlyph(g); } if (f->f_glybase != NULL) free((char *) f->f_glybase); (*f->f_ops->fo_freefont)(f); free(f->f_path); free(f->f_font); free((char *) f); } /* * Get glyph `c' in font `f'. We pull in a few adjacent glyphs here * under the (perhaps naive) assumption that things will go faster * that way. * * TODO: * try different adjacency values * make adjacency a font attribute? (or an op) */ #define ADJ 8 /* must be a power of 2 */ #define GET_ADJ(c, l, h) ((h) = ADJ + ((l) = (c) & ~(ADJ - 1))) struct glyph * GetGlyph(f, c) register struct font *f; int c; { register int i, h, l; GET_ADJ(c, l, h); if (l < f->f_lowch) l = f->f_lowch; if (h > f->f_highch) h = f->f_highch; if (l >= h) return (NULL); for (i = l; i < h; i++) if (f->f_gly[i] == NULL) f->f_gly[i] = AllocGlyph(i); if ((*f->f_ops->fo_getgly)(f, l, h)) { /* * I do not know what to do about this just yet, so: */ panic("getgly fails and I am confused ... help!"); } /* * Apply the appropriate scale factor to the TFM widths. * This makes them come out in scaled points, instead of FIXes. */ ScaleGlyphs(f, l, h); /* ??? */ return (f->f_gly[c]); } /* * Get the raster for glyph g in font f at rotation r. */ char * GetRaster(g, f, r) register struct glyph *g; register struct font *f; int r; { int l, h; /* abort if caller did not ask for rasters in advance */ if ((f->f_flags & FF_RASTERS) == 0) panic("GetRaster(%s)", f->f_path); /* * If there is no raster, get one. Blank characters, * however, never have rasters. */ if (g->g_raster == NULL) { if (!HASRASTER(g)) return (NULL); /* * THE FOLLOWING DEPENDS ON THE ADJACENCY MATCHING THAT IN * GetGlyph() ABOVE. */ GET_ADJ(g->g_index, l, h); if (l < f->f_lowch) l = f->f_lowch; if (h > f->f_highch) h = f->f_highch; if ((*f->f_ops->fo_rasterise)(f, l, h)) error(1, 0, "rasterise fails (out of memory?)"); } if (g->g_rotation != r) SetRotation(g, r); return (g->g_raster); } /* * Return a TeX-style font name, including scale factor. * SHOULD I BOTHER WITH \magstep STYLE NAMES? */ char * Font_TeXName(f) register struct font *f; { static char result[200]; if (f->f_scaled == 1000) return (f->f_font); sprintf(result, "%s scaled %d", f->f_font, f->f_scaled); return (result); }