home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / 2d / font.c < prev    next >
Text File  |  1998-06-08  |  27KB  |  1,278 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /* $Source: f:/miner/source/2d/rcs/font.c $
  14.  * $Revision: 1.30 $
  15.  * $Author: john $
  16.  * $Date: 1995/01/25 20:02:03 $
  17.  *
  18.  * Graphical routines for drawing fonts.
  19.  *
  20.  * $Log: font.c $
  21.  * Revision 1.30  1995/01/25  20:02:03  john
  22.  * Fixed bug with mono clipped fonts only drawing 1 row.
  23.  * 
  24.  * Revision 1.29  1994/12/08  19:03:54  john
  25.  * Made functions use cfile.
  26.  * 
  27.  * Revision 1.28  1994/11/27  23:08:22  matt
  28.  * Changes for new mprintf calling convention
  29.  * 
  30.  * Revision 1.27  1994/11/18  23:54:50  john
  31.  * Made centering work on x = 0x8000 not -0x8000.
  32.  * 
  33.  * Revision 1.26  1994/11/18  22:50:23  john
  34.  * Changed shorts to ints in parameters.
  35.  * 
  36.  * Revision 1.25  1994/11/04  11:10:31  john
  37.  * Took the & out of string sizing.
  38.  * 
  39.  * Revision 1.24  1994/11/04  10:06:36  john
  40.  * Added fade table for fading fonts. Made font that partially clips
  41.  * not print a warning message.
  42.  * 
  43.  * Revision 1.23  1994/09/29  10:09:06  john
  44.  * Added real clipping to text.
  45.  * 
  46.  * Revision 1.22  1994/09/12  19:27:51  john
  47.  * Fixed bug with unclipped fonts clipping.
  48.  * 
  49.  * Revision 1.21  1994/09/12  17:16:59  john
  50.  * Added clipping.
  51.  * 
  52.  * Revision 1.20  1994/08/28  16:43:01  matt
  53.  * Added centering if x==0x8000
  54.  * 
  55.  * Revision 1.19  1994/08/15  15:01:11  matt
  56.  * Close font file after reading
  57.  * 
  58.  * Revision 1.18  1994/08/12  18:17:42  matt
  59.  * Fixed stupid bug that cause first char in font not to print
  60.  * 
  61.  * Revision 1.17  1994/08/11  18:00:17  matt
  62.  * Cleaned up code, fixed string width bug.
  63.  * 
  64.  * Revision 1.16  1994/08/10  18:46:11  matt
  65.  * Fixed a couple of little things
  66.  * 
  67.  * Revision 1.15  1994/08/10  18:36:20  matt
  68.  * Changed font file format.  Made chars not in font plot as spaces.  Font file
  69.  * now stores palette for color font & remaps on load.
  70.  * 
  71.  * Revision 1.14  1994/08/10  12:27:27  matt
  72.  * Took out unneeded int3
  73.  * 
  74.  * Revision 1.13  1994/08/10  12:25:26  matt
  75.  * Added support for colors fonts & kerned fonts
  76.  * Made our own font file format
  77.  * 
  78.  * Revision 1.12  1994/07/22  17:19:00  john
  79.  * made proportional font width be the max width.
  80.  * 
  81.  * Revision 1.11  1994/05/06  12:50:26  john
  82.  * Added supertransparency; neatend things up; took out warnings.
  83.  * 
  84.  * Revision 1.10  1994/01/31  11:08:12  john
  85.  * fixed bug with order of frees.
  86.  * 
  87.  * Revision 1.9  1994/01/31  10:36:40  john
  88.  * Free'd variable size font data.
  89.  * 
  90.  * Revision 1.8  1994/01/27  17:17:40  john
  91.  * Made error if font file doesn't exist.
  92.  * 
  93.  * Revision 1.7  1993/10/26  13:17:48  john
  94.  * *** empty log message ***
  95.  * 
  96.  * Revision 1.6  1993/10/15  16:23:25  john
  97.  * y
  98.  * 
  99.  * Revision 1.5  1993/09/28  19:05:50  john
  100.  * added support for \n in gr_string and gr_get_string_size
  101.  * 
  102.  * Revision 1.4  1993/09/28  12:46:49  matt
  103.  * On error, now call Error() instead of exit().
  104.  * 
  105.  * Revision 1.3  1993/09/20  11:35:31  john
  106.  * *** empty log message ***
  107.  * 
  108.  * Revision 1.2  1993/09/08  15:54:39  john
  109.  * renamed ReadFile to readfontfile to prevent conflicts with others.
  110.  * 
  111.  * Revision 1.1  1993/09/08  11:43:34  john
  112.  * Initial revision
  113.  * 
  114.  *
  115.  */
  116.  
  117. #include <stdarg.h>
  118. #include <stdio.h>
  119. #include <stdlib.h>
  120. #include <conio.h>
  121.  
  122. #include <fcntl.h>
  123. #include <io.h>
  124. #include <sys\types.h>
  125. #include <sys\stat.h>
  126.  
  127. #include "mem.h"
  128.  
  129. #include "gr.h"
  130. #include "grdef.h"
  131. #include "error.h"
  132.  
  133. #include "cfile.h"
  134. #include "mono.h"
  135.  
  136. #define FONT        grd_curcanv->cv_font
  137. #define FG_COLOR    grd_curcanv->cv_font_fg_color
  138. #define BG_COLOR    grd_curcanv->cv_font_bg_color
  139. #define FWIDTH       FONT->ft_w
  140. #define FHEIGHT      FONT->ft_h
  141. #define FBASELINE    FONT->ft_baseline
  142. #define FFLAGS       FONT->ft_flags
  143. #define FMINCHAR     FONT->ft_minchar
  144. #define FMAXCHAR     FONT->ft_maxchar
  145. #define FDATA        FONT->ft_data
  146. #define FCHARS       FONT->ft_chars
  147. #define FWIDTHS      FONT->ft_widths
  148.  
  149. #define BITS_TO_BYTES(x)    (((x)+7)>>3)
  150.  
  151. int gr_internal_string_clipped(int x, int y, char *s );
  152. int gr_internal_string_clipped_m(int x, int y, char *s );
  153.  
  154. char *find_kern_entry(grs_font *font,char first,char second)
  155. {
  156.     ubyte *p=font->ft_kerndata;
  157.  
  158.     while (*p!=255)
  159.         if (p[0]==first && p[1]==second)
  160.             return p;
  161.         else p+=3;
  162.  
  163.     return NULL;
  164.  
  165. }
  166.  
  167. //takes the character AFTER being offset into font
  168. #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
  169.  
  170. //takes the character BEFORE being offset into current font
  171. get_char_width(int c,int c2,int *width,int *spacing)
  172. {
  173.     int letter;
  174.  
  175.     letter = c-FMINCHAR;
  176.  
  177.     if (!INFONT(letter)) {                //not in font, draw as space
  178.         *width=0;
  179.         if (FFLAGS & FT_PROPORTIONAL)
  180.             *spacing = FWIDTH/2;
  181.         else
  182.             *spacing = FWIDTH;
  183.         return;
  184.     }
  185.  
  186.     if (FFLAGS & FT_PROPORTIONAL)
  187.         *width = FWIDTHS[letter];
  188.     else
  189.         *width = FWIDTH;
  190.  
  191.     *spacing = *width;
  192.  
  193.     if (FFLAGS & FT_KERNED)  {
  194.         ubyte *p;
  195.  
  196.         if (!(c2==0 || c2=='\n')) {
  197.             int letter2;
  198.  
  199.             letter2 = c2-FMINCHAR;
  200.  
  201.             if (INFONT(letter2)) {
  202.  
  203.                 p = find_kern_entry(FONT,letter,letter2);
  204.  
  205.                 if (p)
  206.                     *spacing = p[2];
  207.             }
  208.         }
  209.     }
  210. }
  211.  
  212. int get_centered_x(char *s)
  213. {
  214.     int w,w2,s2;
  215.  
  216.     for (w=0;*s!=0 && *s!='\n';s++) {
  217.         get_char_width(s[0],s[1],&w2,&s2);
  218.         w += s2;
  219.     }
  220.  
  221.     return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
  222. }
  223.  
  224.  
  225.  
  226. int gr_internal_string0(int x, int y, char *s )
  227. {
  228.     unsigned char * fp;
  229.     char * text_ptr, * next_row, * text_ptr1;
  230.     int r, BitMask, i, bits, width, spacing, letter, underline;
  231.  
  232.     unsigned int VideoOffset, VideoOffset1;
  233.  
  234.     VideoOffset1 = y * ROWSIZE + x;
  235.  
  236.     next_row = s;
  237.  
  238.     while (next_row != NULL )
  239.     {
  240.         text_ptr1 = next_row;
  241.         next_row = NULL;
  242.  
  243.         if (x==0x8000) {            //centered
  244.             int xx = get_centered_x(text_ptr1);
  245.             VideoOffset1 = y * ROWSIZE + xx;
  246.         }
  247.  
  248.         for (r=0; r<FHEIGHT; r++)
  249.         {
  250.  
  251.             text_ptr = text_ptr1;
  252.  
  253.             VideoOffset = VideoOffset1;
  254.  
  255.             while (*text_ptr)
  256.             {
  257.                 if (*text_ptr == '\n' )
  258.                 {
  259.                     next_row = &text_ptr[1];
  260.                     break;
  261.                 }
  262.  
  263.                 underline = 0;
  264.                 if (*text_ptr == '&' )
  265.                 {
  266.                     if ((r==FBASELINE+2) || (r==FBASELINE+3))
  267.                         underline = 1;
  268.                     text_ptr++;
  269.                 }
  270.  
  271.                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
  272.  
  273.                 letter = *text_ptr-FMINCHAR;
  274.  
  275.                 if (!INFONT(letter)) {    //not in font, draw as space
  276.                     VideoOffset += spacing;
  277.                     text_ptr++;
  278.                     continue;
  279.                 }
  280.  
  281.                 if (FFLAGS & FT_PROPORTIONAL)
  282.                     fp = FCHARS[letter];
  283.                 else
  284.                     fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
  285.  
  286.                 if (underline)
  287.                     for (i=0; i< width; i++ )
  288.                         DATA[VideoOffset++] = FG_COLOR;
  289.                 else
  290.                 {
  291.                     fp += BITS_TO_BYTES(width)*r;
  292.  
  293.                     BitMask = 0;
  294.  
  295.                     for (i=0; i< width; i++ )
  296.                     {
  297.                         if (BitMask==0) {
  298.                             bits = *fp++;
  299.                             BitMask = 0x80;
  300.                         }
  301.  
  302.                         if (bits & BitMask)
  303.                             DATA[VideoOffset++] = FG_COLOR;
  304.                         else
  305.                             DATA[VideoOffset++] = BG_COLOR;
  306.                         BitMask >>= 1;
  307.                     }
  308.                 }
  309.  
  310.                 VideoOffset += spacing-width;        //for kerning
  311.  
  312.                 text_ptr++;
  313.             }
  314.  
  315.             VideoOffset1 += ROWSIZE; y++;
  316.         }
  317.     }
  318.     return 0;
  319. }
  320.  
  321. int gr_internal_string0m(int x, int y, char *s )
  322. {
  323.     unsigned char * fp;
  324.     char * text_ptr, * next_row, * text_ptr1;
  325.     int r, BitMask, i, bits, width, spacing, letter, underline;
  326.  
  327.     unsigned int VideoOffset, VideoOffset1;
  328.  
  329.     VideoOffset1 = y * ROWSIZE + x;
  330.  
  331.     next_row = s;
  332.  
  333.     while (next_row != NULL )
  334.     {
  335.         text_ptr1 = next_row;
  336.         next_row = NULL;
  337.  
  338.         if (x==0x8000) {            //centered
  339.             int xx = get_centered_x(text_ptr1);
  340.             VideoOffset1 = y * ROWSIZE + xx;
  341.         }
  342.  
  343.         for (r=0; r<FHEIGHT; r++)
  344.         {
  345.  
  346.             text_ptr = text_ptr1;
  347.  
  348.             VideoOffset = VideoOffset1;
  349.  
  350.             while (*text_ptr)
  351.             {
  352.                 if (*text_ptr == '\n' )
  353.                 {
  354.                     next_row = &text_ptr[1];
  355.                     break;
  356.                 }
  357.  
  358.                 underline = 0;
  359.                 if (*text_ptr == '&' )
  360.                 {
  361.                     if ((r==FBASELINE+2) || (r==FBASELINE+3))
  362.                         underline = 1;
  363.                     text_ptr++;
  364.                 }
  365.  
  366.                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
  367.  
  368.                 letter = *text_ptr-FMINCHAR;
  369.  
  370.                 if (!INFONT(letter)) {    //not in font, draw as space
  371.                     VideoOffset += spacing;
  372.                     text_ptr++;
  373.                     continue;
  374.                 }
  375.  
  376.                 if (FFLAGS & FT_PROPORTIONAL)
  377.                     fp = FCHARS[letter];
  378.                 else
  379.                     fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
  380.  
  381.                 if (underline)
  382.                     for (i=0; i< width; i++ )
  383.                         DATA[VideoOffset++] = FG_COLOR;
  384.                 else
  385.                 {
  386.                     fp += BITS_TO_BYTES(width)*r;
  387.  
  388.                     BitMask = 0;
  389.  
  390.                     for (i=0; i< width; i++ )
  391.                     {
  392.                         if (BitMask==0) {
  393.                             bits = *fp++;
  394.                             BitMask = 0x80;
  395.                         }
  396.  
  397.                         if (bits & BitMask)
  398.                             DATA[VideoOffset++] = FG_COLOR;
  399.                         else
  400.                             VideoOffset++;
  401.                         BitMask >>= 1;
  402.                     }
  403.                 }
  404.                 text_ptr++;
  405.  
  406.                 VideoOffset += spacing-width;
  407.             }
  408.  
  409.             VideoOffset1 += ROWSIZE; y++;
  410.         }
  411.     }
  412.     return 0;
  413. }
  414.  
  415.  
  416. int gr_internal_string2(int x, int y, char *s )
  417. {
  418.     unsigned char * fp;
  419.     char * text_ptr, * next_row, * text_ptr1;
  420.     int r, BitMask, i, bits, width, spacing, letter, underline;
  421.     int page_switched;
  422.  
  423.     unsigned int VideoOffset, VideoOffset1;
  424.  
  425.     VideoOffset1 = (unsigned int)DATA + y * ROWSIZE + x;
  426.  
  427.     gr_vesa_setpage(VideoOffset1 >> 16);
  428.  
  429.     VideoOffset1 &= 0xFFFF;
  430.  
  431.     next_row = s;
  432.  
  433.     while (next_row != NULL )
  434.     {
  435.         text_ptr1 = next_row;
  436.         next_row = NULL;
  437.  
  438.         if (x==0x8000) {            //centered
  439.             int xx = get_centered_x(text_ptr1);
  440.             VideoOffset1 = y * ROWSIZE + xx;
  441.             gr_vesa_setpage(VideoOffset1 >> 16);
  442.             VideoOffset1 &= 0xFFFF;
  443.         }
  444.  
  445.         for (r=0; r<FHEIGHT; r++)
  446.         {
  447.             text_ptr = text_ptr1;
  448.  
  449.             VideoOffset = VideoOffset1;
  450.  
  451.             page_switched = 0;
  452.  
  453.             while (*text_ptr)
  454.             {
  455.                 if (*text_ptr == '\n' )
  456.                 {
  457.                     next_row = &text_ptr[1];
  458.                     break;
  459.                 }
  460.  
  461.                 underline = 0;
  462.                 if (*text_ptr == '&' )
  463.                 {
  464.                     if ((r==FBASELINE+2) || (r==FBASELINE+3))
  465.                         underline = 1;
  466.                     text_ptr++;
  467.                 }
  468.  
  469.                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
  470.  
  471.                 Assert(width==spacing);        //no kerning support here
  472.  
  473.                 letter = *text_ptr-FMINCHAR;
  474.  
  475.                 if (!INFONT(letter)) {    //not in font, draw as space
  476.                     VideoOffset += spacing;
  477.                     text_ptr++;
  478.                     continue;
  479.                 }
  480.  
  481.                 if (FFLAGS & FT_PROPORTIONAL)
  482.                     fp = FCHARS[letter];
  483.                 else
  484.                     fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
  485.  
  486.                 if (underline)
  487.                 {
  488.                     if ( VideoOffset+width > 0xFFFF )
  489.                     {
  490.                         for (i=0; i< width; i++ )
  491.                         {
  492.                             gr_video_memory[VideoOffset++] = FG_COLOR;
  493.  
  494.                             if (VideoOffset > 0xFFFF )
  495.                             {
  496.                                 VideoOffset -= 0xFFFF + 1;
  497.                                 page_switched = 1;
  498.                                 gr_vesa_incpage();
  499.                             }
  500.                         }
  501.                     }
  502.                     else
  503.                     {
  504.                         for (i=0; i< width; i++ )
  505.                             gr_video_memory[VideoOffset++] = FG_COLOR;
  506.                     }
  507.                 }
  508.                 else
  509.                 {
  510.                     // fp -- dword
  511.                     // VideoOffset
  512.                     // width
  513.  
  514.                     fp += BITS_TO_BYTES(width)*r;
  515.  
  516.                     BitMask = 0;
  517.  
  518.                     if ( VideoOffset+width > 0xFFFF )
  519.                     {
  520.                         for (i=0; i< width; i++ )
  521.                         {
  522.                             if (BitMask==0) {
  523.                                 bits = *fp++;
  524.                                 BitMask = 0x80;
  525.                             }
  526.  
  527.                             if (bits & BitMask)
  528.                                 gr_video_memory[VideoOffset++] = FG_COLOR;
  529.                             else
  530.                                 gr_video_memory[VideoOffset++] = BG_COLOR;
  531.  
  532.                             BitMask >>= 1;
  533.  
  534.                             if (VideoOffset > 0xFFFF )
  535.                             {
  536.                                 VideoOffset -= 0xFFFF + 1;
  537.                                 page_switched = 1;
  538.                                 gr_vesa_incpage();
  539.                             }
  540.  
  541.                         }
  542.                     } else {
  543.  
  544.                         if (width == 8 )
  545.                         {
  546.                             bits = *fp++;
  547.  
  548.                             if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR;
  549.                             else gr_video_memory[VideoOffset+0] = BG_COLOR;
  550.  
  551.                             if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR;
  552.                             else gr_video_memory[VideoOffset+1] = BG_COLOR;
  553.  
  554.                             if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR;
  555.                             else gr_video_memory[VideoOffset+2] = BG_COLOR;
  556.  
  557.                             if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR;
  558.                             else gr_video_memory[VideoOffset+3] = BG_COLOR;
  559.  
  560.                             if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR;
  561.                             else gr_video_memory[VideoOffset+4] = BG_COLOR;
  562.  
  563.                             if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR;
  564.                             else gr_video_memory[VideoOffset+5] = BG_COLOR;
  565.  
  566.                             if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR;
  567.                             else gr_video_memory[VideoOffset+6] = BG_COLOR;
  568.  
  569.                             if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR;
  570.                             else gr_video_memory[VideoOffset+7] = BG_COLOR;
  571.  
  572.                             VideoOffset += 8;
  573.                         } else {
  574.                             for (i=0; i< width/2 ; i++ )
  575.                             {
  576.                                 if (BitMask==0) {
  577.                                     bits = *fp++;
  578.                                     BitMask = 0x80;
  579.                                 }
  580.  
  581.                                 if (bits & BitMask)
  582.                                     gr_video_memory[VideoOffset++] = FG_COLOR;
  583.                                 else
  584.                                     gr_video_memory[VideoOffset++] = BG_COLOR;
  585.                                 BitMask >>= 1;
  586.  
  587.  
  588.                                 // Unroll twice
  589.  
  590.                                 if (BitMask==0) {
  591.                                     bits = *fp++;
  592.                                     BitMask = 0x80;
  593.                                 }
  594.  
  595.                                 if (bits & BitMask)
  596.                                     gr_video_memory[VideoOffset++] = FG_COLOR;
  597.                                 else
  598.                                     gr_video_memory[VideoOffset++] = BG_COLOR;
  599.                                 BitMask >>= 1;
  600.                             }
  601.                         }
  602.                     }
  603.                 }
  604.                 text_ptr++;
  605.             }
  606.  
  607.             VideoOffset1 += ROWSIZE; y++;
  608.  
  609.             if (VideoOffset1 > 0xFFFF ) {
  610.                 VideoOffset1 -= 0xFFFF + 1;
  611.                 if (!page_switched)
  612.                     gr_vesa_incpage();
  613.             }
  614.         }
  615.     }
  616.     return 0;
  617. }
  618.  
  619. int gr_internal_string2m(int x, int y, char *s )
  620. {
  621.     unsigned char * fp;
  622.     char * text_ptr, * next_row, * text_ptr1;
  623.     int r, BitMask, i, bits, width, spacing, letter, underline;
  624.     int page_switched;
  625.  
  626.     unsigned int VideoOffset, VideoOffset1;
  627.  
  628.     VideoOffset1 = (unsigned int)DATA + y * ROWSIZE + x;
  629.  
  630.     gr_vesa_setpage(VideoOffset1 >> 16);
  631.  
  632.     VideoOffset1 &= 0xFFFF;
  633.  
  634.     next_row = s;
  635.  
  636.     while (next_row != NULL )
  637.     {
  638.         text_ptr1 = next_row;
  639.         next_row = NULL;
  640.  
  641.         if (x==0x8000) {            //centered
  642.             int xx = get_centered_x(text_ptr1);
  643.             VideoOffset1 = y * ROWSIZE + xx;
  644.             gr_vesa_setpage(VideoOffset1 >> 16);
  645.             VideoOffset1 &= 0xFFFF;
  646.         }
  647.  
  648.         for (r=0; r<FHEIGHT; r++)
  649.         {
  650.             text_ptr = text_ptr1;
  651.  
  652.             VideoOffset = VideoOffset1;
  653.  
  654.             page_switched = 0;
  655.  
  656.             while (*text_ptr)
  657.             {
  658.                 if (*text_ptr == '\n' )
  659.                 {
  660.                     next_row = &text_ptr[1];
  661.                     break;
  662.                 }
  663.  
  664.                 underline = 0;
  665.                 if (*text_ptr == '&' )
  666.                 {
  667.                     if ((r==FBASELINE+2) || (r==FBASELINE+3))
  668.                         underline = 1;
  669.                     text_ptr++;
  670.                 }
  671.  
  672.                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
  673.  
  674.                 letter = *text_ptr-FMINCHAR;
  675.  
  676.                 if (!INFONT(letter)) {    //not in font, draw as space
  677.                     VideoOffset += width;
  678.                     text_ptr++;
  679.                     continue;
  680.                 }
  681.  
  682.                 if (FFLAGS & FT_PROPORTIONAL)
  683.                     fp = FCHARS[letter];
  684.                 else
  685.                     fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
  686.  
  687.                 if (underline)
  688.                 {
  689.                     if ( VideoOffset+width > 0xFFFF )
  690.                     {
  691.                         for (i=0; i< width; i++ )
  692.                         {
  693.                             gr_video_memory[VideoOffset++] = FG_COLOR;
  694.  
  695.                             if (VideoOffset > 0xFFFF )
  696.                             {
  697.                                 VideoOffset -= 0xFFFF + 1;
  698.                                 page_switched = 1;
  699.                                 gr_vesa_incpage();
  700.                             }
  701.                         }
  702.                     }
  703.                     else
  704.                     {
  705.                         for (i=0; i< width; i++ )
  706.                             gr_video_memory[VideoOffset++] = FG_COLOR;
  707.                     }
  708.                 }
  709.                 else
  710.                 {
  711.                     fp += BITS_TO_BYTES(width)*r;
  712.  
  713.                     BitMask = 0;
  714.  
  715.                     if ( VideoOffset+width > 0xFFFF )
  716.                     {
  717.                         for (i=0; i< width; i++ )
  718.                         {
  719.                             if (BitMask==0) {
  720.                                 bits = *fp++;
  721.                                 BitMask = 0x80;
  722.                             }
  723.  
  724.                             if (bits & BitMask)
  725.                                 gr_video_memory[VideoOffset++] = FG_COLOR;
  726.                             else
  727.                                 VideoOffset++;
  728.  
  729.                             BitMask >>= 1;
  730.  
  731.                             if (VideoOffset > 0xFFFF )
  732.                             {
  733.                                 VideoOffset -= 0xFFFF + 1;
  734.                                 page_switched = 1;
  735.                                 gr_vesa_incpage();
  736.                             }
  737.  
  738.                         }
  739.                     } else {
  740.                         for (i=0; i< width; i++ )
  741.                         {
  742.                             if (BitMask==0) {
  743.                                 bits = *fp++;
  744.                                 BitMask = 0x80;
  745.                             }
  746.  
  747.                             if (bits & BitMask)
  748.                                 gr_video_memory[VideoOffset++] = FG_COLOR;
  749.                             else
  750.                                 VideoOffset++;;
  751.                             BitMask >>= 1;
  752.                         }
  753.                     }
  754.                 }
  755.                 text_ptr++;
  756.  
  757.                 VideoOffset += spacing-width;
  758.             }
  759.  
  760.             VideoOffset1 += ROWSIZE; y++;
  761.  
  762.             if (VideoOffset1 > 0xFFFF ) {
  763.                 VideoOffset1 -= 0xFFFF + 1;
  764.                 if (!page_switched)
  765.                     gr_vesa_incpage();
  766.             }
  767.         }
  768.     }
  769.     return 0;
  770. }
  771.  
  772. //a bitmap for the character
  773. grs_bitmap char_bm = {
  774.                 0,0,0,0,                        //x,y,w,h
  775.                 BM_LINEAR,                    //type
  776.                 BM_FLAG_TRANSPARENT,        //flags
  777.                 0,                                //rowsize
  778.                 NULL,                            //data
  779.                 0                                //selector
  780. };
  781.  
  782. int gr_internal_color_string(int x, int y, char *s )
  783. {
  784.     unsigned char * fp;
  785.     char * text_ptr, * next_row, * text_ptr1;
  786.     int width, spacing,letter;
  787.     int xx,yy;
  788.  
  789.     char_bm.bm_h = FHEIGHT;        //set height for chars of this font
  790.  
  791.     next_row = s;
  792.  
  793.     yy = y;
  794.  
  795.     while (next_row != NULL)
  796.     {
  797.         text_ptr1 = next_row;
  798.         next_row = NULL;
  799.  
  800.         text_ptr = text_ptr1;
  801.  
  802.         xx = x;
  803.  
  804.         if (xx==0x8000)            //centered
  805.             xx = get_centered_x(text_ptr);
  806.  
  807.         while (*text_ptr)
  808.         {
  809.             if (*text_ptr == '\n' )
  810.             {
  811.                 next_row = &text_ptr[1];
  812.                 yy += FHEIGHT;
  813.                 break;
  814.             }
  815.  
  816.             letter = *text_ptr-FMINCHAR;
  817.  
  818.             get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
  819.  
  820.             if (!INFONT(letter)) {    //not in font, draw as space
  821.                 xx += spacing;
  822.                 text_ptr++;
  823.                 continue;
  824.             }
  825.  
  826.             if (FFLAGS & FT_PROPORTIONAL)
  827.                 fp = FCHARS[letter];
  828.             else
  829.                 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
  830.  
  831.             char_bm.bm_w = char_bm.bm_rowsize = width;
  832.  
  833.             char_bm.bm_data = fp;
  834.             gr_bitmapm(xx,yy,&char_bm);
  835.  
  836.             xx += spacing;
  837.  
  838.             text_ptr++;
  839.         }
  840.  
  841.     }
  842.     return 0;
  843. }
  844.  
  845. int gr_string(int x, int y, char *s )
  846. {
  847.     int w, h, aw;
  848.     int clipped=0;
  849.  
  850.     if ( x == 0x8000 )    {
  851.         if ( y<0 ) clipped |= 1;
  852.         gr_get_string_size(s, &w, &h, &aw );
  853.         // for x, since this will be centered, only look at
  854.         // width.
  855.         if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;    
  856.         if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;    
  857.  
  858.         if ( (y+h) < 0 ) clipped |= 2;    
  859.         if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;    
  860.  
  861.     } else {
  862.         if ( (x<0) || (y<0) ) clipped |= 1;
  863.         gr_get_string_size(s, &w, &h, &aw );
  864.         if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;    
  865.         if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;    
  866.         if ( (x+w) < 0 ) clipped |= 2;    
  867.         if ( (y+h) < 0 ) clipped |= 2;    
  868.         if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;    
  869.         if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;    
  870.     }
  871.  
  872.     if ( !clipped )
  873.         return gr_ustring(x, y, s );
  874.     
  875.     if ( clipped & 2 )    {
  876.         // Completely clipped...
  877.         mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
  878.         return 0;
  879.     }
  880.  
  881.     if ( clipped & 1 )    {
  882.         // Partially clipped...
  883.         //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
  884.     }
  885.  
  886.     // Partially clipped...
  887.  
  888.     if (FFLAGS & FT_COLOR) 
  889.         return gr_internal_color_string( x, y, s);
  890.  
  891.     if ( BG_COLOR == -1)
  892.         return gr_internal_string_clipped_m( x, y, s );
  893.     
  894.     return gr_internal_string_clipped( x, y, s );
  895. }
  896.  
  897. int gr_ustring(int x, int y, char *s )
  898. {
  899.     if (FFLAGS & FT_COLOR) {
  900.  
  901.         return gr_internal_color_string(x,y,s);
  902.  
  903.     }
  904.     else
  905.         switch( TYPE )
  906.         {
  907.         case BM_LINEAR:
  908.             if ( BG_COLOR == -1)
  909.                 return gr_internal_string0m(x,y,s);
  910.             else
  911.                 return gr_internal_string0(x,y,s);
  912.         case BM_SVGA:
  913.             if ( BG_COLOR == -1)
  914.                 return gr_internal_string2m(x,y,s);
  915.             else
  916.                 return gr_internal_string2(x,y,s);
  917.         }
  918.  
  919.     return 0;
  920. }
  921.  
  922.  
  923. void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width )
  924. {
  925.     int i = 0, longest_width = 0;
  926.     int width,spacing;
  927.  
  928.     *string_height = FHEIGHT;
  929.     *string_width = 0;
  930.     *average_width = FWIDTH;
  931.  
  932.     if (s != NULL )
  933.     {
  934.         *string_width = 0;
  935.         while (*s)
  936.         {
  937. //            if (*s == '&')
  938. //                s++;
  939.             while (*s == '\n')
  940.             {
  941.                 s++;
  942.                 *string_height += FHEIGHT;
  943.                 *string_width = 0;
  944.             }
  945.  
  946.             if (*s == 0) break;
  947.  
  948.             get_char_width(s[0],s[1],&width,&spacing);
  949.  
  950.             *string_width += spacing;
  951.  
  952.             if (*string_width > longest_width)
  953.                 longest_width = *string_width;
  954.  
  955.             i++;
  956.             s++;
  957.         }
  958.     }
  959.     *string_width = longest_width;
  960. }
  961.  
  962.  
  963. int gr_uprintf( int x, int y, char * format, ... )
  964. {
  965.     char buffer[1000];
  966.     va_list args;
  967.  
  968.     va_start(args, format );
  969.     vsprintf(buffer,format,args);
  970.     return gr_ustring( x, y, buffer );
  971. }
  972.  
  973. int gr_printf( int x, int y, char * format, ... )
  974. {
  975.     char buffer[1000];
  976.     va_list args;
  977.  
  978.     va_start(args, format );
  979.     vsprintf(buffer,format,args);
  980.     return gr_string( x, y, buffer );
  981. }
  982.  
  983. void gr_close_font( grs_font * font )
  984. {
  985.     if (font)
  986.     {
  987.         if ( font->ft_chars ) 
  988.             free( font->ft_chars );
  989.         free( font );
  990.     }
  991. }
  992.  
  993. void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq );
  994. void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count );
  995. #pragma aux decode_data_asm parm [esi] [ecx] [edi] [ebx] modify exact [esi edi eax ebx ecx] = \
  996. "again_ddn:"                            \
  997.     "xor    eax,eax"                \
  998.     "mov    al,[esi]"            \
  999.     "inc    dword ptr [ebx+eax*4]"        \
  1000.     "mov    al,[edi+eax]"        \
  1001.     "mov    [esi],al"            \
  1002.     "inc    esi"                    \
  1003.     "dec    ecx"                    \
  1004.     "jne    again_ddn"
  1005.  
  1006. grs_font * gr_init_font( char * fontname )
  1007. {
  1008.     grs_font *font;
  1009.     int i;
  1010.     unsigned char * ptr;
  1011.     int nchars;
  1012.     CFILE *fontfile;
  1013.     int file_id;
  1014.     int datasize;        //size up to (but not including) palette
  1015.  
  1016.     fontfile = cfopen(fontname, "rb");
  1017.  
  1018.     if (!fontfile)
  1019.         Error( "Can't open font file %s", fontname );
  1020.  
  1021.     cfread(&file_id,sizeof(file_id),1,fontfile);
  1022.     cfread(&datasize,sizeof(datasize),1,fontfile);
  1023.  
  1024.     if (file_id != 'NFSP')
  1025.         Error( "File %s is not a font file", fontname );
  1026.  
  1027.     font = (grs_font *) malloc(datasize);
  1028.  
  1029.     cfread(font,1,datasize,fontfile);
  1030.  
  1031.     nchars = font->ft_maxchar-font->ft_minchar+1;
  1032.  
  1033.     if (font->ft_flags & FT_PROPORTIONAL) {
  1034.  
  1035.         font->ft_widths = (short *) (((int) font->ft_widths) + ((ubyte *) font));
  1036.  
  1037.         font->ft_data = ((int) font->ft_data) + ((ubyte *) font);
  1038.  
  1039.         font->ft_chars = (unsigned char **)malloc( nchars * sizeof(unsigned char *));
  1040.  
  1041.         ptr = font->ft_data;
  1042.  
  1043.         for (i=0; i< nchars; i++ ) {
  1044.             font->ft_chars[i] = ptr;
  1045.             if (font->ft_flags & FT_COLOR)
  1046.                 ptr += font->ft_widths[i] * font->ft_h;
  1047.             else
  1048.                 ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
  1049.         }
  1050.  
  1051.     } else  {
  1052.  
  1053.         font->ft_data = ((unsigned char *) font) + sizeof(*font);
  1054.  
  1055.         font->ft_chars    = NULL;
  1056.         font->ft_widths = NULL;
  1057.  
  1058.         ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
  1059.     }
  1060.  
  1061.     if (font->ft_flags & FT_KERNED) 
  1062.         font->ft_kerndata = ((int) font->ft_kerndata) + ((ubyte *) font);
  1063.  
  1064.  
  1065.     if (font->ft_flags & FT_COLOR) {        //remap palette
  1066.         ubyte palette[256*3];
  1067.         ubyte colormap[256];
  1068.         int freq[256];
  1069.  
  1070.         cfread(palette,3,256,fontfile);        //read the palette
  1071.  
  1072.         build_colormap_good( &palette, colormap, freq );
  1073.     
  1074.         colormap[255] = 255;
  1075.  
  1076.         decode_data_asm(font->ft_data, ptr-font->ft_data, colormap, freq );
  1077.     }
  1078.  
  1079.     cfclose(fontfile);
  1080.  
  1081.     //set curcanv vars
  1082.  
  1083.     FONT        = font;
  1084.     FG_COLOR    = 0;
  1085.     BG_COLOR    = 0;
  1086.  
  1087.     return font;
  1088.  
  1089. }
  1090.  
  1091.  
  1092. void gr_set_fontcolor( int fg, int bg )
  1093. {
  1094.     FG_COLOR    = fg;
  1095.     BG_COLOR    = bg;
  1096. }
  1097.  
  1098. void gr_set_curfont( grs_font * new )
  1099. {
  1100.     FONT = new;
  1101. }
  1102.  
  1103.  
  1104. int gr_internal_string_clipped(int x, int y, char *s )
  1105. {
  1106.     unsigned char * fp;
  1107.     char * text_ptr, * next_row, * text_ptr1;
  1108.     int r, BitMask, i, bits, width, spacing, letter, underline;
  1109.     int x1 = x, last_x;
  1110.     
  1111.     next_row = s;
  1112.  
  1113.     while (next_row != NULL )
  1114.     {
  1115.         text_ptr1 = next_row;
  1116.         next_row = NULL;
  1117.  
  1118.         x = x1;
  1119.         if (x==0x8000)            //centered
  1120.             x = get_centered_x(text_ptr1);
  1121.  
  1122.         last_x = x;
  1123.  
  1124.         for (r=0; r<FHEIGHT; r++)    {
  1125.             text_ptr = text_ptr1;
  1126.             x = last_x;
  1127.  
  1128.             while (*text_ptr)    {
  1129.                 if (*text_ptr == '\n' )    {
  1130.                     next_row = &text_ptr[1];
  1131.                     break;
  1132.                 }
  1133.  
  1134.                 underline = 0;
  1135.                 if (*text_ptr == '&' )    {
  1136.                     if ((r==FBASELINE+2) || (r==FBASELINE+3))
  1137.                         underline = 1;
  1138.                     text_ptr++;
  1139.                 }
  1140.  
  1141.                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
  1142.  
  1143.                 letter = *text_ptr-FMINCHAR;
  1144.  
  1145.                 if (!INFONT(letter)) {    //not in font, draw as space
  1146.                     x += spacing;
  1147.                     text_ptr++;
  1148.                     continue;
  1149.                 }
  1150.  
  1151.                 if (FFLAGS & FT_PROPORTIONAL)
  1152.                     fp = FCHARS[letter];
  1153.                 else
  1154.                     fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
  1155.  
  1156.                 if (underline)    {
  1157.                     for (i=0; i< width; i++ )    {
  1158.                         gr_setcolor(FG_COLOR);
  1159.                         gr_pixel( x++, y );                        
  1160.                     }
  1161.                 } else {
  1162.                     fp += BITS_TO_BYTES(width)*r;
  1163.  
  1164.                     BitMask = 0;
  1165.  
  1166.                     for (i=0; i< width; i++ )    {
  1167.                         if (BitMask==0) {
  1168.                             bits = *fp++;
  1169.                             BitMask = 0x80;
  1170.                         }
  1171.                         if (bits & BitMask)    
  1172.                             gr_setcolor(FG_COLOR);
  1173.                         else
  1174.                             gr_setcolor(BG_COLOR);
  1175.                         gr_pixel( x++, y );                        
  1176.                         BitMask >>= 1;
  1177.                     }
  1178.                 }
  1179.  
  1180.                 x += spacing-width;        //for kerning
  1181.  
  1182.                 text_ptr++;
  1183.             }
  1184.             y++;
  1185.         }
  1186.     }
  1187.     return 0;
  1188. }
  1189.  
  1190. int gr_internal_string_clipped_m(int x, int y, char *s )
  1191. {
  1192.     unsigned char * fp;
  1193.     char * text_ptr, * next_row, * text_ptr1;
  1194.     int r, BitMask, i, bits, width, spacing, letter, underline;
  1195.     int x1 = x, last_x;
  1196.     
  1197.     next_row = s;
  1198.  
  1199.     while (next_row != NULL )
  1200.     {
  1201.         text_ptr1 = next_row;
  1202.         next_row = NULL;
  1203.  
  1204.         x = x1;
  1205.         if (x==0x8000)            //centered
  1206.             x = get_centered_x(text_ptr1);
  1207.  
  1208.         last_x = x;
  1209.  
  1210.         for (r=0; r<FHEIGHT; r++)    {
  1211.             x = last_x;
  1212.  
  1213.             text_ptr = text_ptr1;
  1214.  
  1215.             while (*text_ptr)    {
  1216.                 if (*text_ptr == '\n' )    {
  1217.                     next_row = &text_ptr[1];
  1218.                     break;
  1219.                 }
  1220.  
  1221.                 underline = 0;
  1222.                 if (*text_ptr == '&' )    {
  1223.                     if ((r==FBASELINE+2) || (r==FBASELINE+3))
  1224.                         underline = 1;
  1225.                     text_ptr++;
  1226.                 }
  1227.  
  1228.                 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
  1229.  
  1230.                 letter = *text_ptr-FMINCHAR;
  1231.  
  1232.                 if (!INFONT(letter)) {    //not in font, draw as space
  1233.                     x += spacing;
  1234.                     text_ptr++;
  1235.                     continue;
  1236.                 }
  1237.  
  1238.                 if (FFLAGS & FT_PROPORTIONAL)
  1239.                     fp = FCHARS[letter];
  1240.                 else
  1241.                     fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
  1242.  
  1243.                 if (underline)    {
  1244.                     for (i=0; i< width; i++ )    {
  1245.                         gr_setcolor(FG_COLOR);
  1246.                         gr_pixel( x++, y );                        
  1247.                     }
  1248.                 } else {
  1249.                     fp += BITS_TO_BYTES(width)*r;
  1250.  
  1251.                     BitMask = 0;
  1252.  
  1253.                     for (i=0; i< width; i++ )    {
  1254.                         if (BitMask==0) {
  1255.                             bits = *fp++;
  1256.                             BitMask = 0x80;
  1257.                         }
  1258.                         if (bits & BitMask)    {
  1259.                             gr_setcolor(FG_COLOR);
  1260.                             gr_pixel( x++, y );
  1261.                         } else {
  1262.                             x++;
  1263.                         }                        
  1264.                         BitMask >>= 1;
  1265.                     }
  1266.                 }
  1267.  
  1268.                 x += spacing-width;        //for kerning
  1269.  
  1270.                 text_ptr++;
  1271.             }
  1272.             y++;
  1273.         }
  1274.     }
  1275.     return 0;
  1276. }
  1277. 
  1278.