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-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
14 /* $Source: /cvs/cvsroot/d2x/2d/font.c,v $
17 * $Date: 2001-11-14 09:34:32 $
19 * Graphical routines for drawing fonts.
21 * $Log: not supported by cvs2svn $
22 * Revision 1.9 2001/11/08 10:37:25 bradleyb
23 * free OGL font data when rereading
25 * Revision 1.8 2001/11/04 03:58:25 bradleyb
26 * re-init ogl fonts after remapping colors.
28 * Revision 1.7 2001/11/02 10:46:23 bradleyb
29 * fixed gr_remap_font, minor stuff
31 * Revision 1.6 2001/11/02 02:03:35 bradleyb
32 * Enable OpenGL fonts\!
49 #include "pa_enabl.h" //$$POLY_ACC
67 #define MAX_OPEN_FONTS 50
68 #define FILENAME_LEN 13
70 typedef struct openfont {
71 char filename[FILENAME_LEN];
75 //list of open fonts, for use (for now) for palette remapping
76 openfont open_font[MAX_OPEN_FONTS];
78 #define FONT grd_curcanv->cv_font
79 #define FG_COLOR grd_curcanv->cv_font_fg_color
80 #define BG_COLOR grd_curcanv->cv_font_bg_color
81 #define FWIDTH FONT->ft_w
82 #define FHEIGHT FONT->ft_h
83 #define FBASELINE FONT->ft_baseline
84 #define FFLAGS FONT->ft_flags
85 #define FMINCHAR FONT->ft_minchar
86 #define FMAXCHAR FONT->ft_maxchar
87 #define FDATA FONT->ft_data
88 #define FCHARS FONT->ft_chars
89 #define FWIDTHS FONT->ft_widths
91 #define BITS_TO_BYTES(x) (((x)+7)>>3)
93 int gr_internal_string_clipped(int x, int y, char *s );
94 int gr_internal_string_clipped_m(int x, int y, char *s );
96 ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second)
98 ubyte *p=font->ft_kerndata;
101 if (p[0]==first && p[1]==second)
109 //takes the character AFTER being offset into font
110 #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
112 //takes the character BEFORE being offset into current font
113 void get_char_width(ubyte c,ubyte c2,int *width,int *spacing)
119 if (!INFONT(letter)) { //not in font, draw as space
121 if (FFLAGS & FT_PROPORTIONAL)
128 if (FFLAGS & FT_PROPORTIONAL)
129 *width = FWIDTHS[letter];
135 if (FFLAGS & FT_KERNED) {
138 if (!(c2==0 || c2=='\n')) {
141 letter2 = c2-FMINCHAR;
143 if (INFONT(letter2)) {
145 p = find_kern_entry(FONT,(ubyte)letter,letter2);
154 int get_centered_x(char *s)
158 for (w=0;*s!=0 && *s!='\n';s++) {
162 continue;//skip color codes.
164 get_char_width(s[0],s[1],&w2,&s2);
168 return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
171 //hack to allow color codes to be embedded in strings -MPM
172 //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string.
173 //function must already have orig_color var set (or they could be passed as args...)
174 //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain
175 int gr_message_color_level=1;
176 #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x03)) { \
179 if (gr_message_color_level >= *(text_ptr-1)) \
180 FG_COLOR = *text_ptr - 1; \
184 else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \
185 if (gr_message_color_level >= *text_ptr - 3) \
186 FG_COLOR=orig_color; \
190 int gr_internal_string0(int x, int y, char *s )
193 ubyte * text_ptr, * next_row, * text_ptr1;
194 int r, BitMask, i, bits, width, spacing, letter, underline;
197 unsigned int VideoOffset, VideoOffset1;
201 VideoOffset1 = y * ROWSIZE + x;
205 while (next_row != NULL )
207 text_ptr1 = next_row;
210 if (x==0x8000) { //centered
211 int xx = get_centered_x(text_ptr1);
212 VideoOffset1 = y * ROWSIZE + xx;
215 for (r=0; r<FHEIGHT; r++)
218 text_ptr = text_ptr1;
220 VideoOffset = VideoOffset1;
224 if (*text_ptr == '\n' )
226 next_row = &text_ptr[1];
230 if (*text_ptr == CC_COLOR) {
231 FG_COLOR = *(text_ptr+1);
236 if (*text_ptr == CC_LSPACING) {
237 skip_lines = *(text_ptr+1) - '0';
243 if (*text_ptr == CC_UNDERLINE )
245 if ((r==FBASELINE+2) || (r==FBASELINE+3))
250 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
252 letter = *text_ptr-FMINCHAR;
254 if (!INFONT(letter)) { //not in font, draw as space
255 VideoOffset += spacing;
260 if (FFLAGS & FT_PROPORTIONAL)
263 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
266 for (i=0; i< width; i++ )
267 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
270 fp += BITS_TO_BYTES(width)*r;
274 for (i=0; i< width; i++ )
282 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
284 DATA[VideoOffset++] = (unsigned char) BG_COLOR;
289 VideoOffset += spacing-width; //for kerning
294 VideoOffset1 += ROWSIZE; y++;
298 VideoOffset1 += ROWSIZE * skip_lines;
304 int gr_internal_string0m(int x, int y, char *s )
307 ubyte * text_ptr, * next_row, * text_ptr1;
308 int r, BitMask, i, bits, width, spacing, letter, underline;
311 unsigned int VideoOffset, VideoOffset1;
313 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
317 VideoOffset1 = y * ROWSIZE + x;
321 while (next_row != NULL )
323 text_ptr1 = next_row;
326 if (x==0x8000) { //centered
327 int xx = get_centered_x(text_ptr1);
328 VideoOffset1 = y * ROWSIZE + xx;
331 for (r=0; r<FHEIGHT; r++)
334 text_ptr = text_ptr1;
336 VideoOffset = VideoOffset1;
340 if (*text_ptr == '\n' )
342 next_row = &text_ptr[1];
346 if (*text_ptr == CC_COLOR) {
347 FG_COLOR = *(text_ptr+1);
352 if (*text_ptr == CC_LSPACING) {
353 skip_lines = *(text_ptr+1) - '0';
359 if (*text_ptr == CC_UNDERLINE )
361 if ((r==FBASELINE+2) || (r==FBASELINE+3))
366 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
368 letter = *text_ptr-FMINCHAR;
370 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
371 CHECK_EMBEDDED_COLORS() else{
372 VideoOffset += spacing;
378 if (FFLAGS & FT_PROPORTIONAL)
381 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
384 for (i=0; i< width; i++ )
385 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
388 fp += BITS_TO_BYTES(width)*r;
392 for (i=0; i< width; i++ )
400 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
408 VideoOffset += spacing-width;
411 VideoOffset1 += ROWSIZE;
415 VideoOffset1 += ROWSIZE * skip_lines;
422 int gr_internal_string2(int x, int y, char *s )
425 ubyte * text_ptr, * next_row, * text_ptr1;
426 int r, BitMask, i, bits, width, spacing, letter, underline;
427 int page_switched, skip_lines = 0;
429 unsigned int VideoOffset, VideoOffset1;
431 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
435 gr_vesa_setpage(VideoOffset1 >> 16);
437 VideoOffset1 &= 0xFFFF;
441 while (next_row != NULL )
443 text_ptr1 = next_row;
446 if (x==0x8000) { //centered
447 int xx = get_centered_x(text_ptr1);
448 VideoOffset1 = y * ROWSIZE + xx;
449 gr_vesa_setpage(VideoOffset1 >> 16);
450 VideoOffset1 &= 0xFFFF;
453 for (r=0; r<FHEIGHT; r++)
455 text_ptr = text_ptr1;
457 VideoOffset = VideoOffset1;
463 if (*text_ptr == '\n' )
465 next_row = &text_ptr[1];
469 if (*text_ptr == CC_COLOR) {
470 FG_COLOR = *(text_ptr+1);
475 if (*text_ptr == CC_LSPACING) {
476 skip_lines = *(text_ptr+1) - '0';
482 if (*text_ptr == CC_UNDERLINE )
484 if ((r==FBASELINE+2) || (r==FBASELINE+3))
489 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
491 Assert(width==spacing); //no kerning support here
493 letter = *text_ptr-FMINCHAR;
495 if (!INFONT(letter)) { //not in font, draw as space
496 VideoOffset += spacing;
501 if (FFLAGS & FT_PROPORTIONAL)
504 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
508 if ( VideoOffset+width > 0xFFFF )
510 for (i=0; i< width; i++ )
512 gr_video_memory[VideoOffset++] = FG_COLOR;
514 if (VideoOffset > 0xFFFF )
516 VideoOffset -= 0xFFFF + 1;
524 for (i=0; i< width; i++ )
525 gr_video_memory[VideoOffset++] = FG_COLOR;
534 fp += BITS_TO_BYTES(width)*r;
538 if ( VideoOffset+width > 0xFFFF )
540 for (i=0; i< width; i++ )
548 gr_video_memory[VideoOffset++] = FG_COLOR;
550 gr_video_memory[VideoOffset++] = BG_COLOR;
554 if (VideoOffset > 0xFFFF )
556 VideoOffset -= 0xFFFF + 1;
568 if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR;
569 else gr_video_memory[VideoOffset+0] = BG_COLOR;
571 if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR;
572 else gr_video_memory[VideoOffset+1] = BG_COLOR;
574 if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR;
575 else gr_video_memory[VideoOffset+2] = BG_COLOR;
577 if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR;
578 else gr_video_memory[VideoOffset+3] = BG_COLOR;
580 if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR;
581 else gr_video_memory[VideoOffset+4] = BG_COLOR;
583 if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR;
584 else gr_video_memory[VideoOffset+5] = BG_COLOR;
586 if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR;
587 else gr_video_memory[VideoOffset+6] = BG_COLOR;
589 if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR;
590 else gr_video_memory[VideoOffset+7] = BG_COLOR;
594 for (i=0; i< width/2 ; i++ )
602 gr_video_memory[VideoOffset++] = FG_COLOR;
604 gr_video_memory[VideoOffset++] = BG_COLOR;
616 gr_video_memory[VideoOffset++] = FG_COLOR;
618 gr_video_memory[VideoOffset++] = BG_COLOR;
628 VideoOffset1 += ROWSIZE;
630 if (VideoOffset1 > 0xFFFF ) {
631 VideoOffset1 -= 0xFFFF + 1;
638 VideoOffset1 += ROWSIZE * skip_lines;
644 int gr_internal_string2m(int x, int y, char *s )
647 char * text_ptr, * next_row, * text_ptr1;
648 int r, BitMask, i, bits, width, spacing, letter, underline;
649 int page_switched, skip_lines = 0;
651 unsigned int VideoOffset, VideoOffset1;
653 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
655 gr_vesa_setpage(VideoOffset1 >> 16);
657 VideoOffset1 &= 0xFFFF;
661 while (next_row != NULL )
663 text_ptr1 = next_row;
666 if (x==0x8000) { //centered
667 int xx = get_centered_x(text_ptr1);
668 VideoOffset1 = y * ROWSIZE + xx;
669 gr_vesa_setpage(VideoOffset1 >> 16);
670 VideoOffset1 &= 0xFFFF;
673 for (r=0; r<FHEIGHT; r++)
675 text_ptr = text_ptr1;
677 VideoOffset = VideoOffset1;
683 if (*text_ptr == '\n' )
685 next_row = &text_ptr[1];
689 if (*text_ptr == CC_COLOR) {
690 FG_COLOR = *(text_ptr+1);
695 if (*text_ptr == CC_LSPACING) {
696 skip_lines = *(text_ptr+1) - '0';
702 if (*text_ptr == CC_UNDERLINE )
704 if ((r==FBASELINE+2) || (r==FBASELINE+3))
709 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
711 letter = *text_ptr-FMINCHAR;
713 if (!INFONT(letter)) { //not in font, draw as space
714 VideoOffset += width;
719 if (FFLAGS & FT_PROPORTIONAL)
722 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
726 if ( VideoOffset+width > 0xFFFF )
728 for (i=0; i< width; i++ )
730 gr_video_memory[VideoOffset++] = FG_COLOR;
732 if (VideoOffset > 0xFFFF )
734 VideoOffset -= 0xFFFF + 1;
742 for (i=0; i< width; i++ )
743 gr_video_memory[VideoOffset++] = FG_COLOR;
748 fp += BITS_TO_BYTES(width)*r;
752 if ( VideoOffset+width > 0xFFFF )
754 for (i=0; i< width; i++ )
762 gr_video_memory[VideoOffset++] = FG_COLOR;
768 if (VideoOffset > 0xFFFF )
770 VideoOffset -= 0xFFFF + 1;
777 for (i=0; i< width; i++ )
785 gr_video_memory[VideoOffset++] = FG_COLOR;
794 VideoOffset += spacing-width;
798 VideoOffset1 += ROWSIZE;
800 if (VideoOffset1 > 0xFFFF ) {
801 VideoOffset1 -= 0xFFFF + 1;
808 VideoOffset1 += ROWSIZE * skip_lines;
816 #if defined(POLY_ACC)
817 int gr_internal_string5(int x, int y, char *s )
820 ubyte * text_ptr, * next_row, * text_ptr1;
821 int r, BitMask, i, bits, width, spacing, letter, underline;
824 unsigned int VideoOffset, VideoOffset1;
827 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
831 while (next_row != NULL )
833 text_ptr1 = next_row;
836 if (x==0x8000) { //centered
837 int xx = get_centered_x(text_ptr1);
838 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
841 for (r=0; r<FHEIGHT; r++)
844 text_ptr = text_ptr1;
846 VideoOffset = VideoOffset1;
850 if (*text_ptr == '\n' )
852 next_row = &text_ptr[1];
856 if (*text_ptr == CC_COLOR) {
857 FG_COLOR = *(text_ptr+1);
862 if (*text_ptr == CC_LSPACING) {
863 skip_lines = *(text_ptr+1) - '0';
869 if (*text_ptr == CC_UNDERLINE )
871 if ((r==FBASELINE+2) || (r==FBASELINE+3))
876 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
878 letter = *text_ptr-FMINCHAR;
880 if (!INFONT(letter)) { //not in font, draw as space
881 VideoOffset += spacing * PA_BPP;
886 if (FFLAGS & FT_PROPORTIONAL)
889 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
892 for (i=0; i< width; i++ )
893 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
896 fp += BITS_TO_BYTES(width)*r;
900 for (i=0; i< width; i++ )
908 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
910 { *(short *)(DATA + VideoOffset) = pa_clut[BG_COLOR]; VideoOffset += PA_BPP; }
915 VideoOffset += PA_BPP * (spacing-width); //for kerning
920 VideoOffset1 += ROWSIZE; y++;
924 VideoOffset1 += ROWSIZE * skip_lines;
930 int gr_internal_string5m(int x, int y, char *s )
933 ubyte * text_ptr, * next_row, * text_ptr1;
934 int r, BitMask, i, bits, width, spacing, letter, underline;
937 unsigned int VideoOffset, VideoOffset1;
940 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
944 while (next_row != NULL )
946 text_ptr1 = next_row;
949 if (x==0x8000) { //centered
950 int xx = get_centered_x(text_ptr1);
951 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
954 for (r=0; r<FHEIGHT; r++)
957 text_ptr = text_ptr1;
959 VideoOffset = VideoOffset1;
963 if (*text_ptr == '\n' )
965 next_row = &text_ptr[1];
969 if (*text_ptr == CC_COLOR) {
970 FG_COLOR = *(text_ptr+1);
975 if (*text_ptr == CC_LSPACING) {
976 skip_lines = *(text_ptr+1) - '0';
982 if (*text_ptr == CC_UNDERLINE )
984 if ((r==FBASELINE+2) || (r==FBASELINE+3))
989 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
991 letter = *text_ptr-FMINCHAR;
993 if (!INFONT(letter)) { //not in font, draw as space
994 VideoOffset += spacing * PA_BPP;
999 if (FFLAGS & FT_PROPORTIONAL)
1000 fp = FCHARS[letter];
1002 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1005 for (i=0; i< width; i++ )
1006 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
1009 fp += BITS_TO_BYTES(width)*r;
1013 for (i=0; i< width; i++ )
1021 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
1023 VideoOffset += PA_BPP;
1029 VideoOffset += PA_BPP * (spacing-width);
1032 VideoOffset1 += ROWSIZE; y++;
1035 VideoOffset1 += ROWSIZE * skip_lines;
1043 //a bitmap for the character
1044 grs_bitmap char_bm = {
1047 BM_FLAG_TRANSPARENT, //flags
1050 #ifdef BITMAP_SELECTOR
1057 int gr_internal_color_string(int x, int y, char *s )
1060 ubyte * text_ptr, * next_row, * text_ptr1;
1061 int width, spacing,letter;
1064 char_bm.bm_h = FHEIGHT; //set height for chars of this font
1071 while (next_row != NULL)
1073 text_ptr1 = next_row;
1076 text_ptr = text_ptr1;
1080 if (xx==0x8000) //centered
1081 xx = get_centered_x(text_ptr);
1085 if (*text_ptr == '\n' )
1087 next_row = &text_ptr[1];
1092 letter = *text_ptr-FMINCHAR;
1094 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1096 if (!INFONT(letter)) { //not in font, draw as space
1102 if (FFLAGS & FT_PROPORTIONAL)
1103 fp = FCHARS[letter];
1105 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1107 gr_init_bitmap (&char_bm, BM_LINEAR, 0, 0, width, FHEIGHT, width, fp);
1108 gr_bitmapm(xx,yy,&char_bm);
1120 #include "../main/inferno.h"
1121 #include "ogl_init.h"
1123 //font handling routines for OpenGL - Added 9/25/99 Matthew Mueller - they are here instead of in arch/ogl because they use all these defines
1125 int pow2ize(int x);//from ogl.c
1127 int get_font_total_width(grs_font * font){
1128 if (font->ft_flags & FT_PROPORTIONAL){
1129 int i,w=0,c=font->ft_minchar;
1130 for (i=0;c<=font->ft_maxchar;i++,c++){
1131 if (font->ft_widths[i]<0)
1133 w+=font->ft_widths[i];
1137 return font->ft_w*(font->ft_maxchar-font->ft_minchar+1);
1140 void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){
1141 int nchars = font->ft_maxchar-font->ft_minchar+1;
1142 int r,x,y,nc=0,smallest=999999,smallr=-1,tries;
1143 int smallprop=10000;
1145 for (h=32;h<=256;h*=2){
1146 // h=pow2ize(font->ft_h*rows+gap*(rows-1));
1147 if (font->ft_h>h)continue;
1148 r=(h/(font->ft_h+gap));
1149 w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r);
1155 mprintf((0,"failed to fit (%ix%i, %ic)\n",w,h,nc));
1160 while(y+font->ft_h<=h){
1165 if (font->ft_flags & FT_PROPORTIONAL){
1166 if (x+font->ft_widths[nc]+gap>w)break;
1167 x+=font->ft_widths[nc++]+gap;
1169 if (x+font->ft_w+gap>w)break;
1183 mprintf((0,"fit: %ix%i %i tries\n",w,h,tries));
1185 if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32)
1206 Error("couldn't fit font?\n");
1207 mprintf((0,"using %ix%i\n",*rw,*rh));
1211 void ogl_init_font(grs_font * font){
1212 int nchars = font->ft_maxchar-font->ft_minchar+1;
1213 int i,w,h,tw,th,x,y,curx=0,cury=0;
1215 // char data[32*32*4];
1217 int gap=0;//having a gap just wastes ram, since we don't filter text textures at all.
1219 ogl_font_choose_size(font,gap,&tw,&th);
1220 data=d_malloc(tw*th);
1221 gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data);
1223 font->ft_parent_bitmap.gltexture=ogl_get_free_texture();
1225 font->ft_bitmaps=(grs_bitmap*)d_malloc( nchars * sizeof(grs_bitmap));
1226 mprintf((0,"ogl_init_font %s, %s, nchars=%i, (%ix%i tex)\n",(font->ft_flags & FT_PROPORTIONAL)?"proportional":"fixedwidth",(font->ft_flags & FT_COLOR)?"color":"mono",nchars,tw,th));
1231 for(i=0;i<nchars;i++){
1232 // s[0]=font->ft_minchar+i;
1233 // gr_get_string_size(s,&w,&h,&aw);
1234 if (font->ft_flags & FT_PROPORTIONAL)
1235 w=font->ft_widths[i];
1238 // mprintf((0,"char %i(%ix%i): ",i,w,h));
1240 mprintf((0,"grr\n"));continue;
1247 Error("font doesn't really fit (%i/%i)?\n",i,nchars);
1248 if (font->ft_flags & FT_COLOR) {
1249 if (font->ft_flags & FT_PROPORTIONAL)
1250 fp = font->ft_chars[i];
1252 fp = font->ft_data + i * w*h;
1255 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w];
1258 // gr_init_bitmap(&font->ft_bitmaps[i],BM_LINEAR,0,0,w,h,w,font->);
1260 int BitMask,bits=0,white=gr_find_closest_color(63,63,63);
1261 // if (w*h>sizeof(data))
1262 // Error("ogl_init_font: toobig\n");
1263 if (font->ft_flags & FT_PROPORTIONAL)
1264 fp = font->ft_chars[i];
1266 fp = font->ft_data + i * BITS_TO_BYTES(w)*h;
1269 for (x=0; x< w; x++ )
1277 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white;
1279 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255;
1284 gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h);
1288 if (!(font->ft_flags & FT_COLOR)) {
1289 //use GL_INTENSITY instead of GL_RGB
1290 if (ogl_intensity4_ok){
1291 font->ft_parent_bitmap.gltexture->internalformat=GL_INTENSITY4;
1292 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE;
1293 }else if (ogl_luminance4_alpha4_ok){
1294 font->ft_parent_bitmap.gltexture->internalformat=GL_LUMINANCE4_ALPHA4;
1295 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE_ALPHA;
1296 }else if (ogl_rgba2_ok){
1297 font->ft_parent_bitmap.gltexture->internalformat=GL_RGBA2;
1298 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1300 font->ft_parent_bitmap.gltexture->internalformat=ogl_rgba_format;
1301 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1304 ogl_loadbmtexture_m(&font->ft_parent_bitmap,0);
1307 int ogl_internal_string(int x, int y, char *s )
1309 ubyte * text_ptr, * next_row, * text_ptr1;
1310 int width, spacing,letter;
1312 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
1318 if (grd_curscreen->sc_canvas.cv_bitmap.bm_type != BM_OGL)
1320 while (next_row != NULL)
1322 text_ptr1 = next_row;
1325 text_ptr = text_ptr1;
1329 if (xx==0x8000) //centered
1330 xx = get_centered_x(text_ptr);
1334 if (*text_ptr == '\n' )
1336 next_row = &text_ptr[1];
1341 letter = *text_ptr-FMINCHAR;
1343 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1345 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
1346 CHECK_EMBEDDED_COLORS() else{
1353 // ogl_ubitblt(FONT->ft_bitmaps[letter].bm_w,FONT->ft_bitmaps[letter].bm_h,xx,yy,0,0,&FONT->ft_bitmaps[letter],NULL);
1354 // if (*text_ptr>='0' && *text_ptr<='9'){
1355 if (FFLAGS&FT_COLOR)
1356 gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);
1358 if (grd_curcanv->cv_bitmap.bm_type==BM_OGL)
1359 ogl_ubitmapm_c(xx,yy,&FONT->ft_bitmaps[letter],FG_COLOR);
1361 Error("ogl_internal_string: non-color string to non-ogl dest\n");
1362 // gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);//ignores color..
1375 int gr_internal_color_string(int x, int y, char *s ){
1376 return ogl_internal_string(x,y,s);
1380 int gr_string(int x, int y, char *s )
1385 Assert(FONT != NULL);
1387 if ( x == 0x8000 ) {
1388 if ( y<0 ) clipped |= 1;
1389 gr_get_string_size(s, &w, &h, &aw );
1390 // for x, since this will be centered, only look at
1392 if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1393 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1395 if ( (y+h) < 0 ) clipped |= 2;
1396 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1399 if ( (x<0) || (y<0) ) clipped |= 1;
1400 gr_get_string_size(s, &w, &h, &aw );
1401 if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1402 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1403 if ( (x+w) < 0 ) clipped |= 2;
1404 if ( (y+h) < 0 ) clipped |= 2;
1405 if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;
1406 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1410 return gr_ustring(x, y, s );
1412 if ( clipped & 2 ) {
1413 // Completely clipped...
1414 mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
1418 if ( clipped & 1 ) {
1419 // Partially clipped...
1420 //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
1423 // Partially clipped...
1426 return ogl_internal_string(x,y,s);
1429 if (FFLAGS & FT_COLOR)
1430 return gr_internal_color_string( x, y, s);
1432 if ( BG_COLOR == -1)
1433 return gr_internal_string_clipped_m( x, y, s );
1435 return gr_internal_string_clipped( x, y, s );
1438 int gr_ustring(int x, int y, char *s )
1442 return ogl_internal_string(x,y,s);
1445 if (FFLAGS & FT_COLOR) {
1447 return gr_internal_color_string(x,y,s);
1454 if ( BG_COLOR == -1)
1455 return gr_internal_string0m(x,y,s);
1457 return gr_internal_string0(x,y,s);
1460 if ( BG_COLOR == -1)
1461 return gr_internal_string2m(x,y,s);
1463 return gr_internal_string2(x,y,s);
1465 #if defined(POLY_ACC)
1467 if ( BG_COLOR == -1)
1468 return gr_internal_string5m(x,y,s);
1470 return gr_internal_string5(x,y,s);
1477 void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width )
1479 int i = 0, longest_width = 0;
1482 *string_height = FHEIGHT;
1484 *average_width = FWIDTH;
1491 // if (*s == CC_UNDERLINE)
1496 *string_height += FHEIGHT;
1502 // 1 = next byte specifies color, so skip the 1 and the color value
1505 else if (*s == CC_LSPACING) {
1506 *string_height += *(s+1)-'0';
1509 get_char_width(s[0],s[1],&width,&spacing);
1511 *string_width += spacing;
1513 if (*string_width > longest_width)
1514 longest_width = *string_width;
1521 *string_width = longest_width;
1525 int gr_uprintf( int x, int y, char * format, ... )
1530 va_start(args, format );
1531 vsprintf(buffer,format,args);
1532 return gr_ustring( x, y, buffer );
1535 int gr_printf( int x, int y, char * format, ... )
1540 va_start(args, format );
1541 vsprintf(buffer,format,args);
1542 return gr_string( x, y, buffer );
1545 void gr_close_font( grs_font * font )
1552 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=font;fontnum++);
1553 Assert(fontnum<MAX_OPEN_FONTS); //did we find slot?
1555 open_font[fontnum].ptr = NULL;
1557 if ( font->ft_chars )
1558 d_free( font->ft_chars );
1559 d_free( font->oldfont );
1561 if (font->ft_bitmaps)
1562 d_free( font->ft_bitmaps );
1563 gr_free_bitmap_data(&font->ft_parent_bitmap);
1564 // ogl_freebmtexture(&font->ft_parent_bitmap);
1571 //remap (by re-reading) all the color fonts
1572 void gr_remap_color_fonts()
1576 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1579 font = open_font[fontnum].ptr;
1581 if (font && (font->ft_flags & FT_COLOR))
1582 gr_remap_font(font,open_font[fontnum].filename);
1586 void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq );
1587 void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count );
1589 #pragma aux decode_data_asm parm [esi] [ecx] [edi] [ebx] modify exact [esi edi eax ebx ecx] = \
1593 "inc dword ptr [ebx+eax*4]" \
1594 "mov al,[edi+eax]" \
1602 grs_font * gr_init_font( char * fontname )
1604 static int first_time=1;
1608 unsigned char * ptr;
1612 int32_t datasize; //size up to (but not including) palette
1616 for (i=0;i<MAX_OPEN_FONTS;i++)
1617 open_font[i].ptr = NULL;
1621 //find free font slot
1622 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=NULL;fontnum++);
1623 Assert(fontnum<MAX_OPEN_FONTS); //did we find one?
1625 strncpy(open_font[fontnum].filename,fontname,FILENAME_LEN);
1627 fontfile = cfopen(fontname, "rb");
1630 Error( "Can't open font file %s", fontname );
1632 cfread(&file_id,sizeof(file_id),1,fontfile);
1633 file_id=swapint(file_id);
1634 cfread(&datasize,sizeof(datasize),1,fontfile);
1635 datasize=swapint(datasize);
1637 if (file_id != MAKE_SIG('N','F','S','P'))
1638 Error( "File %s is not a font file", fontname );
1640 font = (old_grs_font *) d_malloc(datasize);
1641 newfont = (grs_font *) d_malloc(sizeof(grs_font));
1642 newfont->oldfont=font;
1644 open_font[fontnum].ptr = newfont;
1646 cfread(font,1,datasize,fontfile);
1648 newfont->ft_flags=swapint(font->ft_flags);
1649 newfont->ft_w=swapshort(font->ft_w);
1650 newfont->ft_h=swapshort(font->ft_h);
1651 newfont->ft_baseline=swapshort(font->ft_baseline);
1652 newfont->ft_maxchar=font->ft_maxchar;
1653 newfont->ft_minchar=font->ft_minchar;
1654 newfont->ft_bytewidth=swapshort(font->ft_bytewidth);
1656 nchars = newfont->ft_maxchar-newfont->ft_minchar+1;
1658 if (newfont->ft_flags & FT_PROPORTIONAL) {
1660 newfont->ft_widths = (short *) (swapint(font->ft_widths) + ((ubyte *) font));
1661 newfont->ft_data = (swapint(font->ft_data)) + ((ubyte *) font);
1662 newfont->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1664 ptr = newfont->ft_data;
1666 for (i=0; i< nchars; i++ ) {
1667 newfont->ft_chars[i] = ptr;
1668 if (newfont->ft_flags & FT_COLOR)
1669 ptr += newfont->ft_widths[i] * newfont->ft_h;
1671 ptr += BITS_TO_BYTES(newfont->ft_widths[i]) * newfont->ft_h;
1676 newfont->ft_data = ((unsigned char *) font) + sizeof(*font);
1677 newfont->ft_chars = NULL;
1678 newfont->ft_widths = NULL;
1680 ptr = newfont->ft_data + (nchars * newfont->ft_w * newfont->ft_h);
1683 if (newfont->ft_flags & FT_KERNED)
1684 newfont->ft_kerndata = swapint(font->ft_kerndata) + ((ubyte *) font);
1686 if (newfont->ft_flags & FT_COLOR) { //remap palette
1687 ubyte palette[256*3];
1688 ubyte colormap[256];
1691 cfread(palette,3,256,fontfile); //read the palette
1693 #ifdef MACINTOSH // swap the first and last palette entries (black and white)
1698 for (i = 0; i < 3; i++) {
1700 palette[i] = palette[765+i];
1704 // we also need to swap the data entries as well. black is white and white is black
1706 for (i = 0; i < ptr-newfont->ft_data; i++) {
1707 if (newfont->ft_data[i] == 0)
1708 newfont->ft_data[i] = 255;
1709 else if (newfont->ft_data[i] == 255)
1710 newfont->ft_data[i] = 0;
1716 build_colormap_good( (ubyte *)&palette, colormap, freq );
1718 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // chaged from colormap[255] = 255 to this for macintosh
1720 decode_data_asm(newfont->ft_data, ptr-newfont->ft_data, colormap, freq );
1726 // memcpy(newfont,font,(ubyte*)&newfont->oldfont-(ubyte*)newfont);//fill in newfont data from oldfont struct
1727 // mprintf((0,"%i %i %i\n",sizeof(grs_font),sizeof(old_grs_font),(ubyte*)&newfont->oldfont-(ubyte*)newfont));
1737 char tests[]="abcdefghij1234.A";
1738 gr_get_string_size(tests,&x,&y,&aw);
1739 // newfont->ft_aw=x/(float)strlen(tests);
1743 ogl_init_font(newfont);
1750 //remap a font by re-reading its data & palette
1751 void gr_remap_font( grs_font *font, char * fontname )
1757 int32_t datasize; //size up to (but not including) palette
1760 if (! (font->ft_flags & FT_COLOR))
1763 fontfile = cfopen(fontname, "rb");
1766 Error( "Can't open font file %s", fontname );
1768 file_id = cfile_read_int(fontfile);
1769 datasize = cfile_read_int(fontfile);
1771 if (file_id != MAKE_SIG('N','F','S','P'))
1772 Error( "File %s is not a font file", fontname );
1774 nchars = font->ft_maxchar-font->ft_minchar+1;
1776 //compute data length
1778 if (font->ft_flags & FT_PROPORTIONAL) {
1780 for (i=0; i< nchars; i++ ) {
1781 if (font->ft_flags & FT_COLOR)
1782 data_len += font->ft_widths[i] * font->ft_h;
1784 data_len += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1788 data_len = nchars * font->ft_w * font->ft_h;
1790 cfread(font->oldfont, 1, datasize, fontfile); //read raw data
1792 if (font->ft_flags & FT_COLOR) { //remap palette
1793 ubyte palette[256*3];
1794 ubyte colormap[256];
1797 cfseek(fontfile,-sizeof(palette),SEEK_END);
1799 cfread(palette,3,256,fontfile); //read the palette
1801 #ifdef MACINTOSH // swap the first and last palette entries (black and white)
1806 for (i = 0; i < 3; i++) {
1808 palette[i] = palette[765+i];
1812 // we also need to swap the data entries as well. black is white and white is black
1814 for (i = 0; i < data_len; i++) {
1815 if (font->ft_data[i] == 0)
1816 font->ft_data[i] = 255;
1817 else if (font->ft_data[i] == 255)
1818 font->ft_data[i] = 0;
1824 build_colormap_good( (ubyte *)&palette, colormap, freq );
1826 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255;
1828 decode_data_asm(font->ft_data, data_len, colormap, freq );
1835 if (font->ft_bitmaps)
1836 d_free( font->ft_bitmaps );
1837 gr_free_bitmap_data(&font->ft_parent_bitmap);
1838 // ogl_freebmtexture(&font->ft_parent_bitmap);
1840 ogl_init_font(font);
1845 void gr_set_fontcolor( int fg, int bg )
1851 void gr_set_curfont( grs_font * new )
1857 int gr_internal_string_clipped(int x, int y, char *s )
1860 char * text_ptr, * next_row, * text_ptr1;
1861 int r, BitMask, i, bits, width, spacing, letter, underline;
1868 while (next_row != NULL )
1870 text_ptr1 = next_row;
1874 if (x==0x8000) //centered
1875 x = get_centered_x(text_ptr1);
1879 for (r=0; r<FHEIGHT; r++) {
1880 text_ptr = text_ptr1;
1884 if (*text_ptr == '\n' ) {
1885 next_row = &text_ptr[1];
1889 if (*text_ptr == CC_COLOR) {
1890 FG_COLOR = *(text_ptr+1);
1895 if (*text_ptr == CC_LSPACING) {
1896 Int3(); // Warning: skip lines not supported for clipped strings.
1902 if (*text_ptr == CC_UNDERLINE ) {
1903 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1908 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1910 letter = *text_ptr-FMINCHAR;
1912 if (!INFONT(letter)) { //not in font, draw as space
1918 if (FFLAGS & FT_PROPORTIONAL)
1919 fp = FCHARS[letter];
1921 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1924 for (i=0; i< width; i++ ) {
1925 gr_setcolor(FG_COLOR);
1929 fp += BITS_TO_BYTES(width)*r;
1933 for (i=0; i< width; i++ ) {
1939 gr_setcolor(FG_COLOR);
1941 gr_setcolor(BG_COLOR);
1947 x += spacing-width; //for kerning
1957 int gr_internal_string_clipped_m(int x, int y, char *s )
1960 char * text_ptr, * next_row, * text_ptr1;
1961 int r, BitMask, i, bits, width, spacing, letter, underline;
1968 while (next_row != NULL )
1970 text_ptr1 = next_row;
1974 if (x==0x8000) //centered
1975 x = get_centered_x(text_ptr1);
1979 for (r=0; r<FHEIGHT; r++) {
1982 text_ptr = text_ptr1;
1985 if (*text_ptr == '\n' ) {
1986 next_row = &text_ptr[1];
1990 if (*text_ptr == CC_COLOR) {
1991 FG_COLOR = *(text_ptr+1);
1996 if (*text_ptr == CC_LSPACING) {
1997 Int3(); // Warning: skip lines not supported for clipped strings.
2003 if (*text_ptr == CC_UNDERLINE ) {
2004 if ((r==FBASELINE+2) || (r==FBASELINE+3))
2009 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
2011 letter = *text_ptr-FMINCHAR;
2013 if (!INFONT(letter)) { //not in font, draw as space
2019 if (FFLAGS & FT_PROPORTIONAL)
2020 fp = FCHARS[letter];
2022 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
2025 for (i=0; i< width; i++ ) {
2026 gr_setcolor(FG_COLOR);
2030 fp += BITS_TO_BYTES(width)*r;
2034 for (i=0; i< width; i++ ) {
2039 if (bits & BitMask) {
2040 gr_setcolor(FG_COLOR);
2049 x += spacing-width; //for kerning