home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / vopl / hershey.lha / hershey / src / htext.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-02  |  11.6 KB  |  689 lines

  1. /*
  2.  * This file is directly from the VOGLE library. It's simply had a few
  3.  * gratuitous name changes and some comments added.
  4.  */
  5. #ifdef SGI
  6. #include <gl.h>
  7. #include <device.h>
  8. #else
  9. #include "vogl.h"
  10. #include "vodevice.h"
  11. #endif
  12.  
  13. #include <stdio.h>
  14. #include <fcntl.h>
  15. #ifdef TC
  16. extern double sin();
  17. extern double cos();
  18. #else
  19. #include <math.h>
  20. #endif
  21. #include <string.h>
  22.  
  23. #ifndef PATH_SIZE
  24. #define    PATH_SIZE    256
  25. #endif
  26.  
  27. #ifdef PC
  28. #ifndef FONTLIB
  29. #define    FONTLIB        "c:\\lib\\hershey\\"
  30. #endif
  31. #else
  32. #ifndef FONTLIB
  33. #define    FONTLIB        "/usr/local/lib/hershey/"
  34. #endif
  35. #endif
  36.  
  37. #define    ABS(a)        ((a) < 0 ? -(a) : (a))
  38. #define    MAX(a, b)    ((a) < (b) ? (b) : (a))
  39. #define    XCOORD(x)    (int)((x) - 'R')
  40. #define    YCOORD(y)    (int)('R' - (y))
  41.  
  42. #ifndef PI
  43. #define PI     3.14159265358979
  44. #endif
  45.  
  46. #ifndef D2R
  47. #define D2R    (PI / 180.0)
  48. #endif
  49.  
  50. #define LEFT        0    /* The default */
  51. #define CENTERED    1
  52. #define RIGHT        2
  53.  
  54. static    float    tcos = 1.0, tsin = 0.0;            /* For rotations */
  55. static    float    SCSIZEX = 1.0, SCSIZEY = 1.0;        /* Scale factors */
  56. static    int    Justify = LEFT;
  57. static    int    Fixedwidth = 0;            /* Some flags     */
  58. static    short    nchars;                    /* No. in font     */
  59. int    hLoaded = 0;
  60.  
  61. static    hershfont();
  62.  
  63. static    char    old_font[PATH_SIZE] = "";    /* So we don't have to reload it */
  64. static    char    fpath[PATH_SIZE] = "";    
  65.  
  66.  
  67. static    struct    {
  68.     int    as;    /* Max ascender of a character in this font */
  69.     int    dec;    /* Max decender of a character in this font */
  70.     int    mw;    /* Max width of a character in this font */
  71.     char    *p;    /* All the vectors in the font */
  72.     char    **ind;    /* Pointers to where the chars start in p */
  73. } ftab;
  74.  
  75. float    hstrlength();    /* Length of a set of Hershey characters  */
  76. float    hgetfontwidth(); /* The width of this font */
  77. float    hgetfontheight(); /* The height of this font */
  78. extern    char    *hallocate();
  79. extern    char    *getenv();
  80.  
  81. /*
  82.  * hfont
  83.  *     loads in a hershey font.
  84.  */
  85. void
  86. hfont(name)
  87.     char    *name;
  88. {
  89.     /*
  90.      * check we aren't loading the same font twice in a row
  91.      */
  92.     if (*name == '/') {
  93.         if (strcmp(strrchr(name, '/') + 1, old_font) == 0)
  94.             return;
  95.  
  96.     } else if (strcmp(name, old_font) == 0)
  97.         return;
  98.  
  99.     /*
  100.      * Try and load it
  101.      */
  102.     if (!hershfont(name)) {
  103.         fprintf(stderr, "hershlib: problem reading font file '%s'.\n", name);
  104.         exit(1);
  105.     }
  106.  
  107.     /*
  108.      * Save the name of it...
  109.      */
  110.     if (*name == '/')
  111.         strcpy(old_font, strrchr(name, '/') + 1);
  112.     else 
  113.         strcpy(old_font, name);
  114.  
  115. }
  116.  
  117. /*
  118.  * hnumchars
  119.  *
  120.  *    Return the number of characters in the currently loaded hershey font.
  121.  */
  122. int
  123. hnumchars()
  124. {
  125.  
  126.     check_loaded("hnumchars");
  127.  
  128.     return((int)nchars);
  129. }
  130.  
  131. /*
  132.  * hsetpath
  133.  *
  134.  *    Set the path of the directory to look for fonts.
  135.  */
  136. void
  137. hsetpath(path)
  138.     char    *path;
  139. {
  140.     int    l;
  141.  
  142.     strcpy(fpath, path);
  143.  
  144.     l = strlen(fpath);
  145.  
  146. #ifdef PC
  147.     if (fpath[l] != '\\')
  148.         strcat(fpath, "\\");
  149. #else
  150.     if (fpath[l] != '/')
  151.         strcat(fpath, "/");
  152. #endif
  153. }
  154.  
  155. /*
  156.  * hershfont
  157.  *
  158.  * Load in a hershey font. First try the environment, then the font library,
  159.  * if that fails try the current directory, otherwise return 0.
  160.  */
  161. static int
  162. hershfont(fontname)
  163.     char    *fontname;
  164. {
  165.     FILE    *fp, *fopen();
  166.     int    i, j;
  167.     short    nvects, n;
  168.     char    *flib;
  169.     char    path[PATH_SIZE];    
  170.     
  171.     if (fpath[0] != '\0') {
  172.         strcpy(path, fpath);
  173.         strcat(path, fontname);
  174.     } else if ((flib = getenv("HFONTLIB")) != (char *)NULL) {
  175.         strcpy(path, flib);
  176. #ifdef PC
  177.         strcat(path, "\\");
  178. #else
  179.         strcat(path, "/");
  180. #endif
  181.         strcat(path, fontname);
  182.     } else if ((flib = getenv("VFONTLIB")) != (char *)NULL) {
  183.         strcpy(path, flib);    /* To be compatible with VOGLE */
  184. #ifdef PC
  185.         strcat(path, "\\");
  186. #else
  187.         strcat(path, "/");
  188. #endif
  189.         strcat(path, fontname);
  190.     } else {
  191.         strcpy(path, FONTLIB);
  192. #ifdef PC
  193.         strcat(path, "\\");
  194. #else
  195.         strcat(path, "/");
  196. #endif
  197.         strcat(path, fontname);
  198.     }
  199.  
  200. #ifdef PC
  201.     if ((fp = fopen(path, "r+b")) == (FILE *)NULL) 
  202.         if ((fp = fopen(fontname, "r+b")) == (FILE *)NULL) {
  203. #else
  204.     if ((fp = fopen(path, "r")) == (FILE *)NULL)
  205.         if ((fp = fopen(fontname, "r")) == (FILE *)NULL) {
  206. #endif
  207.             fprintf(stderr, "hershlib: Can't open Hershey fontfile '%s' or './%s'.\n", path, fontname);
  208.             exit(1);
  209.         }
  210.  
  211.     if (fread(&nchars, sizeof(nchars), 1, fp) != 1)
  212.         return (0);
  213.  
  214. #ifdef DEBUG
  215.     printf("nchars = %d\n", nchars);
  216. #endif
  217.  
  218.     if (fread(&nvects, sizeof(nvects), 1, fp) != 1)
  219.         return(0);
  220.  
  221. #ifdef DEBUG
  222.     printf("nvects = %d\n", nvects);
  223. #endif
  224.     if (fread(&n, sizeof(n), 1,  fp) != 1)
  225.         return(0);
  226.  
  227. #ifdef DEBUG
  228.     printf("ftab.as = %d\n", n);
  229. #endif
  230.     ftab.as = (int)n;
  231.  
  232.     if (fread(&n, sizeof(n), 1, fp) != 1)
  233.         return(0);
  234.  
  235. #ifdef DEBUG
  236.     printf("ftab.dec = %d\n", n);
  237. #endif
  238.     ftab.dec = (int)n;
  239.  
  240.     if (fread(&n, sizeof(n), 1, fp) != 1)
  241.         return(0);
  242.  
  243. #ifdef DEBUG
  244.     printf("ftab.mw = %d\n", n);
  245. #endif
  246.  
  247.     ftab.mw = (int)n;
  248.  
  249.     /*
  250.      *  Allocate space for it all....
  251.      */
  252.     if (hLoaded) {
  253.         if (ftab.ind[0])
  254.             free(ftab.ind[0]);
  255.         if (ftab.ind)
  256.             free(ftab.ind);
  257.         hLoaded = 0;
  258.     }
  259.  
  260.     ftab.ind = (char **)hallocate(sizeof(char *)*(nchars + 1));
  261.  
  262.     ftab.p = (char *)hallocate((unsigned)(2 * nvects));
  263.  
  264.     /*
  265.      *  As we read in each character, figure out what ind should be
  266.      */
  267.  
  268.     for (i = 0; i < nchars; i++) {
  269.         if (fread(&n , sizeof(n), 1, fp) != 1)
  270.             return(0);
  271.  
  272.         if (fread(ftab.p, 1, (unsigned)n, fp) != (unsigned)n)
  273.             return(0);
  274.  
  275.         ftab.ind[i] = ftab.p;
  276.         ftab.p += n;
  277.     }
  278.  
  279.     ftab.ind[nchars] = ftab.p;    /* To Terminate the last one */
  280.  
  281.     fclose(fp);
  282.     hLoaded = 1;
  283.     return(1);
  284. }
  285.  
  286. /*
  287.  * hgetcharsize
  288.  *
  289.  *    get the width and height of a single character. At the moment, for
  290.  * the hershey characters, the height returned is always that of the
  291.  * difference between the maximun descender and ascender.
  292.  *
  293.  */
  294. void
  295. hgetcharsize(c, width, height)
  296.     char    c;
  297.     float    *width, *height;
  298. {
  299.     check_loaded("hgetcharsize");
  300.     
  301.     *height = (float)(ftab.as - ftab.dec) * SCSIZEY;
  302.  
  303.     if (Fixedwidth)
  304.         *width = (float)ftab.mw * SCSIZEX;
  305.     else
  306.         *width = (float)(ftab.ind[c - 32][1] - ftab.ind[c - 32][0]) * SCSIZEX;
  307. }
  308.  
  309. /*
  310.  * hdrawchar
  311.  *
  312.  * Display a character from the currently loaded font.
  313.  */
  314. void
  315. hdrawchar(c)
  316.     int    c;
  317. {
  318.     char    *p, *e;
  319.     int    Move, i, x, y, xt, yt;
  320.     float    xs, ys, xp, yp, tmp, xtmp, ytmp;
  321.  
  322.     check_loaded("hdrawchar");
  323.  
  324.     if ((i = c - 32) < 0)
  325.         i = 0;
  326.     if (i >= nchars)
  327.         i = nchars - 1;
  328.  
  329.     Move = 1;
  330.  
  331.     xt = yt = 0;
  332.     if (Justify == LEFT) {
  333.         xt = (Fixedwidth ? -ftab.mw / 2 : XCOORD(ftab.ind[i][0]));
  334.         yt = ftab.dec;
  335.     } else if (Justify == RIGHT) {
  336.         xt = (Fixedwidth ?  ftab.mw / 2 : -XCOORD(ftab.ind[i][0]));
  337.         yt = ftab.dec;
  338.     }
  339.  
  340.     e = ftab.ind[i + 1];
  341.     p = ftab.ind[i] + 2;
  342.  
  343.     xtmp = ytmp = 0.0;
  344.  
  345.     while(p < e) {
  346.         x = XCOORD((int)*p++);
  347.         y = YCOORD((int)*p++);
  348.         if (x != -50) {            /* means move */
  349.             xp = (float)(x - xt) * SCSIZEX;
  350.             yp = (float)(y - yt) * SCSIZEY;
  351.             tmp = xp;
  352.             xp = tcos*tmp - tsin*yp;
  353.             yp = tsin*tmp + tcos*yp;
  354.             xs = xp - xtmp;
  355.             ys = yp - ytmp;
  356.             xtmp = xp;
  357.             ytmp = yp;
  358.             if (Move) {
  359.                 Move = 0;
  360.                 rmv((Coord)xs, (Coord)ys, (Coord)0.0);
  361.             } else
  362.                 rdr((Coord)xs, (Coord)ys, (Coord)0.0);
  363.  
  364.         } else {
  365.             Move = 1;
  366.         }
  367.     }
  368.     /*
  369.      * Move to right hand of character.
  370.        BLARK
  371.      */
  372.     
  373.     tmp = Fixedwidth ? (float)ftab.mw : (float)(ftab.ind[i][1] - ftab.ind[i][0]);
  374.  
  375.     tmp *= SCSIZEX;
  376.     xs = tcos * tmp - xtmp;
  377.     ys = tsin * tmp - ytmp;
  378.     rmv((Coord)xs, (Coord)ys, 0.0);
  379. }
  380.  
  381. /*
  382.  * htextsize
  383.  *
  384.  * set software character scaling values 
  385.  *
  386.  * Note: Only changes software char size. Should be called
  387.  * after a font has been loaded.
  388.  *
  389.  */
  390. void
  391. htextsize(width, height)
  392.     float    width, height;
  393. {
  394.     float    a;
  395.  
  396.     check_loaded("htextsize");
  397.  
  398.     a = (float)MAX((int)ftab.mw, (int)(ftab.as - ftab.dec));
  399.  
  400.     SCSIZEX = width / ABS(a);
  401.     SCSIZEY = height / ABS(a);
  402. }
  403.  
  404. /*
  405.  * hgetfontwidth
  406.  *
  407.  * Return the maximum Width of the current font.
  408.  *
  409.  */
  410. float
  411. hgetfontwidth()
  412. {
  413.     check_loaded("hgetfontwidth");
  414.  
  415.     return((float)(SCSIZEX * MAX((int)ftab.mw, (int)(ftab.as - ftab.dec))));
  416. }
  417.  
  418. /* 
  419.  * hgetfontheight
  420.  *
  421.  * Return the maximum Height of the current font
  422.  */
  423. float 
  424. hgetfontheight()
  425. {
  426.     check_loaded("hgetfontheight");
  427.  
  428.     return((float)(SCSIZEY * MAX((int)ftab.mw, (int)(ftab.as - ftab.dec))));
  429. }
  430.  
  431. /*
  432.  * hgetfontsize
  433.  *
  434.  * Get the current character size in user coords.
  435.  * For software Hershey fonts, the character width is that of
  436.  * a the widest character and the height the height of the tallest.
  437.  *
  438.  */
  439. void
  440. hgetfontsize(cw, ch)
  441.     float     *cw, *ch;
  442. {
  443.     check_loaded("hgetfontsize");
  444.  
  445.     *cw = hgetfontwidth();
  446.     *ch = hgetfontheight();
  447. }
  448.  
  449. /*
  450.  * hgetdecender
  451.  *
  452.  *    Return the maximum decender of the current font.
  453.  *     (In world coords).
  454.  */
  455. float
  456. hgetdecender()
  457. {
  458.     check_loaded("hgetdecender");
  459.  
  460.     return((float)ftab.dec * SCSIZEY);
  461. }
  462.  
  463. /*
  464.  * hgetascender
  465.  *
  466.  *    Return the maximum assender of the current font.
  467.  *     (In world coords).
  468.  */
  469. float
  470. hgetascender()
  471. {
  472.     check_loaded("hgetascender");
  473.  
  474.     return((float)ftab.as * SCSIZEY);
  475. }
  476.  
  477. /*
  478.  * hcharstr
  479.  *
  480.  * Draw a string from the current pen position.
  481.  *
  482.  */
  483. void
  484. hcharstr(string)
  485.     char     *string;
  486. {
  487.     float    width, height, cx, cy, cz;
  488.     char    *str = string, c;
  489.     int    oldJustify;
  490.  
  491.     check_loaded("hcharstr");
  492.  
  493.     height = hgetfontheight();
  494.     width = hstrlength(string);
  495.  
  496.     cx = cy = 0.0;
  497.     if (Justify == CENTERED) {
  498.         height /= 2.0;
  499.         width /= 2.0;
  500.         cx =  height * tsin - width * tcos;
  501.         cy = -height * tcos - width * tsin;
  502.     } else if (Justify == RIGHT) {
  503.         height = 0.0;
  504.         cx =  height * tsin - width * tcos;
  505.         cy = -height * tcos - width * tsin;
  506.     }
  507.     rmv((Coord)cx, (Coord)cy, (Coord)0.0);
  508.  
  509.  
  510.     /*
  511.      * For the duration of hershey strings, turn off
  512.      * "Justify" as we have already compensated
  513.      * for it in hcharstr()
  514.      */
  515.     oldJustify = Justify;
  516.     Justify = 0;
  517.  
  518.     /*
  519.      * Now display each character
  520.      *
  521.      */
  522.     while (c = *str++)
  523.         hdrawchar(c);
  524.     
  525.     Justify = oldJustify;
  526.  
  527. }
  528.  
  529. /*
  530.  * istrlength
  531.  *
  532.  * Find out the length of a string in raw "Hershey coordinates".
  533.  */
  534. static    int
  535. istrlength(s)
  536.     char    *s;
  537. {
  538.     char    c;
  539.     int    i, len = 0;
  540.     
  541.     if (Fixedwidth)
  542.         return((int)(strlen(s) * ftab.mw));
  543.     else {
  544.         while (c = *s++) {
  545.             if ((i = (int)c - 32) < 0 || i >= nchars)
  546.                 i = nchars - 1;
  547.  
  548.             len += (ftab.ind[i][1] - ftab.ind[i][0]);
  549.         }
  550.         return (len);
  551.     }
  552. }
  553.  
  554. /*
  555.  * hstrlength
  556.  *
  557.  * Find out the length (in world coords) of a string.
  558.  *
  559.  */
  560. float
  561. hstrlength(s)
  562.     char    *s;
  563. {
  564.     check_loaded("hstrlength");
  565.  
  566.     return((float)(istrlength(s) * SCSIZEX));
  567. }
  568.  
  569. /*
  570.  * hboxtext
  571.  *
  572.  * Draw text so it fits in a "box" - note only works with hershey text
  573.  */
  574. void
  575. hboxtext(x, y, l, h, s)
  576.     float    x, y, l, h;
  577.     char    *s;
  578. {
  579.     float    oscsizex, oscsizey, cz;
  580.  
  581.     check_loaded("hboxtext");
  582.  
  583.     oscsizex = SCSIZEX;
  584.     oscsizey = SCSIZEY;
  585.     /*
  586.      * set width so string length is the same a "l" 
  587.      */
  588.     SCSIZEX = l / (float)istrlength(s);
  589.  
  590.     /* 
  591.      * set character height so it's the same as "h" 
  592.      */
  593.     SCSIZEY = h / (float)(ftab.as - ftab.dec);
  594.  
  595.     move2(x, y);
  596.     hcharstr(s);
  597.  
  598.     SCSIZEX = oscsizex;
  599.     SCSIZEY = oscsizey;
  600. }
  601.  
  602. /*
  603.  * hboxfit
  604.  *
  605.  * Set up the scales etc for text so that a string of "nchars" characters
  606.  * of the maximum width in the font fits in a box.
  607.  */
  608. void
  609. hboxfit(l, h, nchars)
  610.     float    l, h;
  611.     int    nchars;
  612. {
  613.     check_loaded("hboxfit");
  614.  
  615.     SCSIZEX = l / (float)(nchars * ftab.mw);
  616.     SCSIZEY = h / (float)(ftab.as - ftab.dec);
  617. }
  618.  
  619. /*
  620.  * The following can be set without a font actually being loaded....
  621.  */
  622. /*
  623.  * hcenter
  624.  *
  625.  *    Turns centering of text on or off
  626.  */
  627. void
  628. hcentertext(onoff)
  629.     int    onoff;
  630. {
  631.     Justify = (onoff != 0 ? CENTERED : LEFT);
  632. }
  633.  
  634. /*
  635.  * hrightjustify
  636.  *
  637.  *    Right Justifies the text.
  638.  */
  639. void
  640. hrightjustify(onoff)
  641.     int    onoff;
  642. {
  643.     Justify = (onoff != 0 ? RIGHT : LEFT);
  644. }
  645.  
  646. /*
  647.  * hleftjustify
  648.  *
  649.  *    Left Justifies the text. (the default).
  650.  */
  651. void
  652. hleftjustify(onoff)
  653.     int    onoff;
  654. {
  655.     Justify = (onoff != 0 ? LEFT : RIGHT);
  656. }
  657.  
  658. /*
  659.  * fixedwidth
  660.  *
  661.  *    Turns fixedwidth text on or off
  662.  */
  663. void
  664. hfixedwidth(onoff)
  665.     int    onoff;
  666. {
  667.     Fixedwidth = onoff;
  668. }
  669.  
  670. /*
  671.  * htextang
  672.  *
  673.  * set software character angle in degrees
  674.  *
  675.  * strings will be written along a line 'ang' degrees from the 
  676.  * horizontal screen direction
  677.  *
  678.  * Note: only changes software character angle
  679.  *
  680.  */
  681. void
  682. htextang(ang)
  683.     float    ang;
  684. {
  685.  
  686.     tcos = cos((double)(ang * D2R));
  687.     tsin = sin((double)(ang * D2R));
  688. }
  689.