home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / s / stex2-18.zip / SeeTeX / libtex / rstfont.c < prev    next >
C/C++ Source or Header  |  1990-07-25  |  6KB  |  300 lines

  1. /*
  2.  * Copyright (c) 1987, 1989 University of Maryland
  3.  * Department of Computer Science.  All rights reserved.
  4.  * Permission to copy for any purpose is hereby granted
  5.  * so long as this copyright notice remains intact.
  6.  *
  7.  * The code in this file was partially derived from another version by
  8.  * Tim Morgan at UCI.
  9.  *
  10.  * TODO:
  11.  *    test
  12.  */
  13.  
  14. #ifndef lint
  15. static char rcsid[] = "$Header$";
  16. #endif
  17.  
  18. #include <stdio.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <errno.h>
  22. #include "types.h"
  23. #include "error.h"
  24. #include "font.h"
  25. #include "fio.h"
  26.  
  27. /*
  28.  * RST (Imagen's font format) font operations.
  29.  */
  30. static int rst_read(), rst_getgly(), rst_rasterise();
  31. static void rst_freefont();
  32.  
  33. #ifdef UCI
  34. #define D 1.0 /* I think */
  35. #else
  36. #define D 150.0
  37. #endif
  38.  
  39. struct    fontops rstops =
  40.     { "rst", 0, D, rst_read, rst_getgly, rst_rasterise, rst_freefont };
  41.  
  42. #undef D
  43.  
  44. /*
  45.  * Local info.
  46.  */
  47. #define    FILEMARK_SIZE    8    /* header `file mark' bytes to skip */
  48.  
  49. /*
  50.  * rc describes one RST character information block.
  51.  */
  52. struct rc {
  53.     i16    rc_height;    /* character height (pixels) */
  54.     i16    rc_width;    /* character width (pixels) */
  55.     i16    rc_yoffset;    /* Y offset of reference point */
  56.     i16    rc_xoffset;    /* X offset of reference point */
  57.     i32    rc_rastoff;    /* raster offset */
  58.     i32    rc_TFMwidth;    /* TFM width */
  59. };
  60.  
  61. /*
  62.  * rst_details are the RST-specific font details.
  63.  *
  64.  * We keep track of the number of characters converted to internal
  65.  * glyph form, and when all have been done, we discard the now-
  66.  * useless details.
  67.  */
  68. struct rst_details {
  69.     int    rd_unconv;    /* number of characters unconverted */
  70.     struct    rc *rd_rc;    /* `font directory' */
  71.     char    *rd_ras;    /* raster space, until converted */
  72.     long    rd_rastbase;    /* adjust rc_rastoff by rastbase */
  73. };
  74.  
  75. /*
  76.  * Get the rst_details from font f.
  77.  */
  78. #define    ftord(f) ((struct rst_details *)(f)->f_details)
  79.  
  80. extern    errno;
  81. char    *malloc();
  82. long    ftell();
  83.  
  84. /*
  85.  * Read an RST file.
  86.  */
  87. static int
  88. rst_read(f, fd)
  89.     struct font *f;
  90.     int fd;
  91. {
  92.     register struct rst_details *rd;
  93.     register FILE *fp;
  94.     register struct rc *rc;
  95.     register int i;
  96.     int saverr;
  97.     long presize, diroff;
  98.     i32 firstgly, lastgly;
  99.  
  100.     fp = NULL;
  101.     if ((rd = (struct rst_details *)malloc(sizeof *rd)) == 0)
  102.         goto fail;
  103.     rd->rd_ras = 0;
  104.     rd->rd_rc = 0;
  105.  
  106.     /*
  107.      * Read the header.
  108.      */
  109.     errno = 0;        /* try to make errno meaningful */
  110.     if ((fp = fdopen(fd, "r")) == NULL) {
  111.         if (errno == 0)
  112.             errno = EMFILE;
  113.         goto fail;
  114.     }
  115.     (void) fseek(fp, (long)FILEMARK_SIZE, 0);
  116.     fGetWord(fp, presize);    /* bytes in preamble (from FILEMARK_SIZE+2) */
  117.     presize += 2 + FILEMARK_SIZE;
  118.     i = getc(fp);        /* version */
  119.     if (i != 0) {
  120.         error(0, 0, "Warning: strange RST version (%d) in \"%s\"", i,
  121.             f->f_path);
  122.         errno = EINVAL;
  123.         goto fail;
  124.     }
  125.     fGet3Byte(fp, diroff);    /* offset to glyph directory */
  126.     fGetWord(fp, firstgly);    /* first glyph */
  127.     fGetWord(fp, lastgly);    /* last glyph (inclusive) */
  128.     lastgly++;        /* make it exclusive */
  129.  
  130.     (void) GetLong(fp);    /* mag */
  131.     fGetLong(fp, f->f_design_size);
  132.     /* interline, interword, rotation, charadv, lineadv */
  133.     (void) fseek(fp, (long)(4 + 4 + 2 + 1 + 1), 1);
  134.     fGetLong(fp, f->f_checksum);
  135.     f->f_hppp = 0;        /* ??? */
  136.     f->f_vppp = 0;
  137.  
  138.     /*
  139.      * Read the glyph directory.
  140.      */
  141.     i = lastgly - firstgly;
  142.     rd->rd_rc = (struct rc *)malloc((unsigned) (i * sizeof(*rc)));
  143.     if (rd->rd_rc == 0)
  144.         goto fail;
  145.     (void) fseek(fp, presize, 0);
  146.     for (rc = rd->rd_rc; --i >= 0; rc++) {
  147.         fGetWord(fp, rc->rc_height);
  148.         fGetWord(fp, rc->rc_width);
  149.         fGetWord(fp, rc->rc_yoffset);
  150.         fGetWord(fp, rc->rc_xoffset);
  151.         fGetLong(fp, rc->rc_TFMwidth);
  152.         fGet3Byte(fp, rc->rc_rastoff);
  153.     }
  154.  
  155.     /*
  156.      * Set up the raster pointer (if we need rasters).
  157.      */
  158.     if (f->f_flags & FF_RASTERS) {
  159.         struct stat st;
  160.  
  161.         rd->rd_rastbase = ftell(fp);
  162.         /* back to unbuffered I/O */
  163.         (void) fstat(fd, &st);
  164.         i = st.st_size - presize - 15 * (lastgly - firstgly);
  165.         if (i < 0)
  166.             error(1, 0, "calculated raster size < 0 for \"%s\"",
  167.                 f->f_path);
  168.         if (i != 0)  {
  169.             if ((rd->rd_ras = malloc((unsigned) i)) == 0)
  170.                 goto fail;
  171.             (void) lseek(fd, rd->rd_rastbase, 0);
  172.             if (read(fd, rd->rd_ras, i) != i)
  173.                 goto fail;
  174.         }
  175.     }
  176.  
  177.     f->f_details = (char *) rd;
  178.     if (FontHasGlyphs(f, firstgly, lastgly))
  179.         goto fail;
  180.  
  181.     (void) fclose(fp);
  182.     rd->rd_unconv = lastgly - firstgly;
  183.     return (0);
  184.  
  185. fail:
  186.     saverr = errno;
  187.     if (rd) {
  188.         if (rd->rd_rc)
  189.             free((char *)rd->rd_rc);
  190.         if (rd->rd_ras)
  191.             free(rd->rd_ras);
  192.         free((char *) rd);
  193.     }
  194.     if (fp)
  195.         (void) fclose(fp);
  196.     else
  197.         (void) close(fd);
  198.     errno = saverr;
  199.     return (-1);
  200. }
  201.  
  202. /*
  203.  * Obtain the specified range of glyphs.
  204.  */
  205. static int
  206. rst_getgly(f, l, h)
  207.     register struct font *f;
  208.     int l;
  209.     register int h;
  210. {
  211.     register struct glyph *g;
  212.     register struct rc *rc;
  213.     register int i;
  214.     struct rst_details *rd;
  215.  
  216.     if ((rd = ftord(f)) == NULL)
  217.         panic("rst_getgly");
  218.  
  219.     /*
  220.      * By definition, all glyphs are valid.  Just copy the
  221.      * RST information.
  222.      */
  223.     for (rc = &rd->rd_rc[(i = l) - f->f_lowch]; i < h; i++, rc++) {
  224.         g = f->f_gly[i];
  225.         g->g_flags = GF_VALID;
  226.         g->g_height = rc->rc_height;
  227.         g->g_width = rc->rc_width;
  228.         g->g_yorigin = rc->rc_yoffset;
  229.         g->g_xorigin = rc->rc_xoffset;
  230.         g->g_rawtfmwidth = rc->rc_TFMwidth;
  231.     }
  232.     return (0);
  233. }
  234.  
  235. /*
  236.  * Obtain rasters for the specified glyphs.
  237.  */
  238. static int
  239. rst_rasterise(f, l, h)
  240.     register struct font *f;
  241.     int l;
  242.     register int h;
  243. {
  244.     register struct glyph *g;
  245.     register struct rc *rc;
  246.     register struct rst_details *rd;
  247.     register int i;
  248.     unsigned sz;
  249.  
  250.     if ((rd = ftord(f)) == NULL)
  251.         panic("rst_rasterise details==0");
  252.     if (rd->rd_ras == NULL)
  253.         panic("rst_rasterise rd_ras==NULL");
  254.     for (rc = &rd->rd_rc[(i = l) - f->f_lowch]; i < h; i++, rc++) {
  255.         g = f->f_gly[i];
  256.         if (!HASRASTER(g))
  257.             continue;
  258.         if (rc->rc_rastoff == 0) {
  259.             error(1, 0, "bad RST glyph %d in \"%s\"",
  260.                 g->g_index, f->f_path);
  261.         } else {
  262.             sz = ((g->g_width + 7) >> 3) * g->g_height;
  263.             if ((g->g_raster = malloc(sz)) == NULL)
  264.                 return (-1);    /* ??? */
  265.             g->g_rotation = ROT_NORM;
  266.             bcopy(rd->rd_ras + rc->rc_rastoff - rd->rd_rastbase,
  267.                 g->g_raster, sz);
  268.         }
  269.     }
  270.  
  271.     /*
  272.      * If we have converted all the characters, dump the
  273.      * pre-conversion rasters.  In fact, dump everything.
  274.      */
  275.     rd->rd_unconv -= h - l;
  276.     if (rd->rd_unconv == 0) {
  277.         free((char *)rd->rd_rc);
  278.         free(rd->rd_ras);
  279.         free((char *)rd);
  280.         f->f_details = NULL;
  281.     }
  282.     return (0);
  283. }
  284.  
  285. /*
  286.  * Discard the font details.
  287.  */
  288. static void
  289. rst_freefont(f)
  290.     struct font *f;
  291. {
  292.     struct rst_details *rd;
  293.  
  294.     if ((rd = ftord(f)) != NULL) {
  295.         free((char *)rd->rd_rc);
  296.         free(rd->rd_ras);
  297.         free((char *)rd);
  298.     }
  299. }
  300.