1 /* $Id: font.c,v 1.11 2002-07-17 21:55:19 bradleyb Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
16 * Graphical routines for drawing fonts.
32 #include "pa_enabl.h" //$$POLY_ACC
50 #define MAX_OPEN_FONTS 50
51 #define FILENAME_LEN 13
53 typedef struct openfont {
54 char filename[FILENAME_LEN];
58 //list of open fonts, for use (for now) for palette remapping
59 openfont open_font[MAX_OPEN_FONTS];
61 #define FONT grd_curcanv->cv_font
62 #define FG_COLOR grd_curcanv->cv_font_fg_color
63 #define BG_COLOR grd_curcanv->cv_font_bg_color
64 #define FWIDTH FONT->ft_w
65 #define FHEIGHT FONT->ft_h
66 #define FBASELINE FONT->ft_baseline
67 #define FFLAGS FONT->ft_flags
68 #define FMINCHAR FONT->ft_minchar
69 #define FMAXCHAR FONT->ft_maxchar
70 #define FDATA FONT->ft_data
71 #define FCHARS FONT->ft_chars
72 #define FWIDTHS FONT->ft_widths
74 #define BITS_TO_BYTES(x) (((x)+7)>>3)
76 int gr_internal_string_clipped(int x, int y, char *s );
77 int gr_internal_string_clipped_m(int x, int y, char *s );
79 ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second)
81 ubyte *p=font->ft_kerndata;
84 if (p[0]==first && p[1]==second)
92 //takes the character AFTER being offset into font
93 #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
95 //takes the character BEFORE being offset into current font
96 void get_char_width(ubyte c,ubyte c2,int *width,int *spacing)
102 if (!INFONT(letter)) { //not in font, draw as space
104 if (FFLAGS & FT_PROPORTIONAL)
111 if (FFLAGS & FT_PROPORTIONAL)
112 *width = FWIDTHS[letter];
118 if (FFLAGS & FT_KERNED) {
121 if (!(c2==0 || c2=='\n')) {
124 letter2 = c2-FMINCHAR;
126 if (INFONT(letter2)) {
128 p = find_kern_entry(FONT,(ubyte)letter,letter2);
137 int get_centered_x(char *s)
141 for (w=0;*s!=0 && *s!='\n';s++) {
145 continue;//skip color codes.
147 get_char_width(s[0],s[1],&w2,&s2);
151 return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
154 //hack to allow color codes to be embedded in strings -MPM
155 //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string.
156 //function must already have orig_color var set (or they could be passed as args...)
157 //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain
158 int gr_message_color_level=1;
159 #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x03)) { \
162 if (gr_message_color_level >= *(text_ptr-1)) \
163 FG_COLOR = *text_ptr - 1; \
167 else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \
168 if (gr_message_color_level >= *text_ptr - 3) \
169 FG_COLOR=orig_color; \
173 int gr_internal_string0(int x, int y, char *s )
176 ubyte * text_ptr, * next_row, * text_ptr1;
177 int r, BitMask, i, bits, width, spacing, letter, underline;
180 unsigned int VideoOffset, VideoOffset1;
184 VideoOffset1 = y * ROWSIZE + x;
188 while (next_row != NULL )
190 text_ptr1 = next_row;
193 if (x==0x8000) { //centered
194 int xx = get_centered_x(text_ptr1);
195 VideoOffset1 = y * ROWSIZE + xx;
198 for (r=0; r<FHEIGHT; r++)
201 text_ptr = text_ptr1;
203 VideoOffset = VideoOffset1;
207 if (*text_ptr == '\n' )
209 next_row = &text_ptr[1];
213 if (*text_ptr == CC_COLOR) {
214 FG_COLOR = *(text_ptr+1);
219 if (*text_ptr == CC_LSPACING) {
220 skip_lines = *(text_ptr+1) - '0';
226 if (*text_ptr == CC_UNDERLINE )
228 if ((r==FBASELINE+2) || (r==FBASELINE+3))
233 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
235 letter = *text_ptr-FMINCHAR;
237 if (!INFONT(letter)) { //not in font, draw as space
238 VideoOffset += spacing;
243 if (FFLAGS & FT_PROPORTIONAL)
246 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
249 for (i=0; i< width; i++ )
250 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
253 fp += BITS_TO_BYTES(width)*r;
257 for (i=0; i< width; i++ )
265 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
267 DATA[VideoOffset++] = (unsigned char) BG_COLOR;
272 VideoOffset += spacing-width; //for kerning
277 VideoOffset1 += ROWSIZE; y++;
281 VideoOffset1 += ROWSIZE * skip_lines;
287 int gr_internal_string0m(int x, int y, char *s )
290 ubyte * text_ptr, * next_row, * text_ptr1;
291 int r, BitMask, i, bits, width, spacing, letter, underline;
294 unsigned int VideoOffset, VideoOffset1;
296 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
300 VideoOffset1 = y * ROWSIZE + x;
304 while (next_row != NULL )
306 text_ptr1 = next_row;
309 if (x==0x8000) { //centered
310 int xx = get_centered_x(text_ptr1);
311 VideoOffset1 = y * ROWSIZE + xx;
314 for (r=0; r<FHEIGHT; r++)
317 text_ptr = text_ptr1;
319 VideoOffset = VideoOffset1;
323 if (*text_ptr == '\n' )
325 next_row = &text_ptr[1];
329 if (*text_ptr == CC_COLOR) {
330 FG_COLOR = *(text_ptr+1);
335 if (*text_ptr == CC_LSPACING) {
336 skip_lines = *(text_ptr+1) - '0';
342 if (*text_ptr == CC_UNDERLINE )
344 if ((r==FBASELINE+2) || (r==FBASELINE+3))
349 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
351 letter = *text_ptr-FMINCHAR;
353 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
354 CHECK_EMBEDDED_COLORS() else{
355 VideoOffset += spacing;
361 if (FFLAGS & FT_PROPORTIONAL)
364 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
367 for (i=0; i< width; i++ )
368 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
371 fp += BITS_TO_BYTES(width)*r;
375 for (i=0; i< width; i++ )
383 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
391 VideoOffset += spacing-width;
394 VideoOffset1 += ROWSIZE;
398 VideoOffset1 += ROWSIZE * skip_lines;
405 int gr_internal_string2(int x, int y, char *s )
408 ubyte * text_ptr, * next_row, * text_ptr1;
409 int r, BitMask, i, bits, width, spacing, letter, underline;
410 int page_switched, skip_lines = 0;
412 unsigned int VideoOffset, VideoOffset1;
414 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
418 gr_vesa_setpage(VideoOffset1 >> 16);
420 VideoOffset1 &= 0xFFFF;
424 while (next_row != NULL )
426 text_ptr1 = next_row;
429 if (x==0x8000) { //centered
430 int xx = get_centered_x(text_ptr1);
431 VideoOffset1 = y * ROWSIZE + xx;
432 gr_vesa_setpage(VideoOffset1 >> 16);
433 VideoOffset1 &= 0xFFFF;
436 for (r=0; r<FHEIGHT; r++)
438 text_ptr = text_ptr1;
440 VideoOffset = VideoOffset1;
446 if (*text_ptr == '\n' )
448 next_row = &text_ptr[1];
452 if (*text_ptr == CC_COLOR) {
453 FG_COLOR = *(text_ptr+1);
458 if (*text_ptr == CC_LSPACING) {
459 skip_lines = *(text_ptr+1) - '0';
465 if (*text_ptr == CC_UNDERLINE )
467 if ((r==FBASELINE+2) || (r==FBASELINE+3))
472 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
474 Assert(width==spacing); //no kerning support here
476 letter = *text_ptr-FMINCHAR;
478 if (!INFONT(letter)) { //not in font, draw as space
479 VideoOffset += spacing;
484 if (FFLAGS & FT_PROPORTIONAL)
487 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
491 if ( VideoOffset+width > 0xFFFF )
493 for (i=0; i< width; i++ )
495 gr_video_memory[VideoOffset++] = FG_COLOR;
497 if (VideoOffset > 0xFFFF )
499 VideoOffset -= 0xFFFF + 1;
507 for (i=0; i< width; i++ )
508 gr_video_memory[VideoOffset++] = FG_COLOR;
517 fp += BITS_TO_BYTES(width)*r;
521 if ( VideoOffset+width > 0xFFFF )
523 for (i=0; i< width; i++ )
531 gr_video_memory[VideoOffset++] = FG_COLOR;
533 gr_video_memory[VideoOffset++] = BG_COLOR;
537 if (VideoOffset > 0xFFFF )
539 VideoOffset -= 0xFFFF + 1;
551 if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR;
552 else gr_video_memory[VideoOffset+0] = BG_COLOR;
554 if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR;
555 else gr_video_memory[VideoOffset+1] = BG_COLOR;
557 if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR;
558 else gr_video_memory[VideoOffset+2] = BG_COLOR;
560 if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR;
561 else gr_video_memory[VideoOffset+3] = BG_COLOR;
563 if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR;
564 else gr_video_memory[VideoOffset+4] = BG_COLOR;
566 if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR;
567 else gr_video_memory[VideoOffset+5] = BG_COLOR;
569 if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR;
570 else gr_video_memory[VideoOffset+6] = BG_COLOR;
572 if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR;
573 else gr_video_memory[VideoOffset+7] = BG_COLOR;
577 for (i=0; i< width/2 ; i++ )
585 gr_video_memory[VideoOffset++] = FG_COLOR;
587 gr_video_memory[VideoOffset++] = BG_COLOR;
599 gr_video_memory[VideoOffset++] = FG_COLOR;
601 gr_video_memory[VideoOffset++] = BG_COLOR;
611 VideoOffset1 += ROWSIZE;
613 if (VideoOffset1 > 0xFFFF ) {
614 VideoOffset1 -= 0xFFFF + 1;
621 VideoOffset1 += ROWSIZE * skip_lines;
627 int gr_internal_string2m(int x, int y, char *s )
630 char * text_ptr, * next_row, * text_ptr1;
631 int r, BitMask, i, bits, width, spacing, letter, underline;
632 int page_switched, skip_lines = 0;
634 unsigned int VideoOffset, VideoOffset1;
636 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
638 gr_vesa_setpage(VideoOffset1 >> 16);
640 VideoOffset1 &= 0xFFFF;
644 while (next_row != NULL )
646 text_ptr1 = next_row;
649 if (x==0x8000) { //centered
650 int xx = get_centered_x(text_ptr1);
651 VideoOffset1 = y * ROWSIZE + xx;
652 gr_vesa_setpage(VideoOffset1 >> 16);
653 VideoOffset1 &= 0xFFFF;
656 for (r=0; r<FHEIGHT; r++)
658 text_ptr = text_ptr1;
660 VideoOffset = VideoOffset1;
666 if (*text_ptr == '\n' )
668 next_row = &text_ptr[1];
672 if (*text_ptr == CC_COLOR) {
673 FG_COLOR = *(text_ptr+1);
678 if (*text_ptr == CC_LSPACING) {
679 skip_lines = *(text_ptr+1) - '0';
685 if (*text_ptr == CC_UNDERLINE )
687 if ((r==FBASELINE+2) || (r==FBASELINE+3))
692 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
694 letter = *text_ptr-FMINCHAR;
696 if (!INFONT(letter)) { //not in font, draw as space
697 VideoOffset += width;
702 if (FFLAGS & FT_PROPORTIONAL)
705 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
709 if ( VideoOffset+width > 0xFFFF )
711 for (i=0; i< width; i++ )
713 gr_video_memory[VideoOffset++] = FG_COLOR;
715 if (VideoOffset > 0xFFFF )
717 VideoOffset -= 0xFFFF + 1;
725 for (i=0; i< width; i++ )
726 gr_video_memory[VideoOffset++] = FG_COLOR;
731 fp += BITS_TO_BYTES(width)*r;
735 if ( VideoOffset+width > 0xFFFF )
737 for (i=0; i< width; i++ )
745 gr_video_memory[VideoOffset++] = FG_COLOR;
751 if (VideoOffset > 0xFFFF )
753 VideoOffset -= 0xFFFF + 1;
760 for (i=0; i< width; i++ )
768 gr_video_memory[VideoOffset++] = FG_COLOR;
777 VideoOffset += spacing-width;
781 VideoOffset1 += ROWSIZE;
783 if (VideoOffset1 > 0xFFFF ) {
784 VideoOffset1 -= 0xFFFF + 1;
791 VideoOffset1 += ROWSIZE * skip_lines;
799 #if defined(POLY_ACC)
800 int gr_internal_string5(int x, int y, char *s )
803 ubyte * text_ptr, * next_row, * text_ptr1;
804 int r, BitMask, i, bits, width, spacing, letter, underline;
807 unsigned int VideoOffset, VideoOffset1;
810 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
814 while (next_row != NULL )
816 text_ptr1 = next_row;
819 if (x==0x8000) { //centered
820 int xx = get_centered_x(text_ptr1);
821 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
824 for (r=0; r<FHEIGHT; r++)
827 text_ptr = text_ptr1;
829 VideoOffset = VideoOffset1;
833 if (*text_ptr == '\n' )
835 next_row = &text_ptr[1];
839 if (*text_ptr == CC_COLOR) {
840 FG_COLOR = *(text_ptr+1);
845 if (*text_ptr == CC_LSPACING) {
846 skip_lines = *(text_ptr+1) - '0';
852 if (*text_ptr == CC_UNDERLINE )
854 if ((r==FBASELINE+2) || (r==FBASELINE+3))
859 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
861 letter = *text_ptr-FMINCHAR;
863 if (!INFONT(letter)) { //not in font, draw as space
864 VideoOffset += spacing * PA_BPP;
869 if (FFLAGS & FT_PROPORTIONAL)
872 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
875 for (i=0; i< width; i++ )
876 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
879 fp += BITS_TO_BYTES(width)*r;
883 for (i=0; i< width; i++ )
891 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
893 { *(short *)(DATA + VideoOffset) = pa_clut[BG_COLOR]; VideoOffset += PA_BPP; }
898 VideoOffset += PA_BPP * (spacing-width); //for kerning
903 VideoOffset1 += ROWSIZE; y++;
907 VideoOffset1 += ROWSIZE * skip_lines;
913 int gr_internal_string5m(int x, int y, char *s )
916 ubyte * text_ptr, * next_row, * text_ptr1;
917 int r, BitMask, i, bits, width, spacing, letter, underline;
920 unsigned int VideoOffset, VideoOffset1;
923 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
927 while (next_row != NULL )
929 text_ptr1 = next_row;
932 if (x==0x8000) { //centered
933 int xx = get_centered_x(text_ptr1);
934 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
937 for (r=0; r<FHEIGHT; r++)
940 text_ptr = text_ptr1;
942 VideoOffset = VideoOffset1;
946 if (*text_ptr == '\n' )
948 next_row = &text_ptr[1];
952 if (*text_ptr == CC_COLOR) {
953 FG_COLOR = *(text_ptr+1);
958 if (*text_ptr == CC_LSPACING) {
959 skip_lines = *(text_ptr+1) - '0';
965 if (*text_ptr == CC_UNDERLINE )
967 if ((r==FBASELINE+2) || (r==FBASELINE+3))
972 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
974 letter = *text_ptr-FMINCHAR;
976 if (!INFONT(letter)) { //not in font, draw as space
977 VideoOffset += spacing * PA_BPP;
982 if (FFLAGS & FT_PROPORTIONAL)
985 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
988 for (i=0; i< width; i++ )
989 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
992 fp += BITS_TO_BYTES(width)*r;
996 for (i=0; i< width; i++ )
1004 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
1006 VideoOffset += PA_BPP;
1012 VideoOffset += PA_BPP * (spacing-width);
1015 VideoOffset1 += ROWSIZE; y++;
1018 VideoOffset1 += ROWSIZE * skip_lines;
1026 //a bitmap for the character
1027 grs_bitmap char_bm = {
1030 BM_FLAG_TRANSPARENT, //flags
1033 #ifdef BITMAP_SELECTOR
1040 int gr_internal_color_string(int x, int y, char *s )
1043 ubyte * text_ptr, * next_row, * text_ptr1;
1044 int width, spacing,letter;
1047 char_bm.bm_h = FHEIGHT; //set height for chars of this font
1054 while (next_row != NULL)
1056 text_ptr1 = next_row;
1059 text_ptr = text_ptr1;
1063 if (xx==0x8000) //centered
1064 xx = get_centered_x(text_ptr);
1068 if (*text_ptr == '\n' )
1070 next_row = &text_ptr[1];
1075 letter = *text_ptr-FMINCHAR;
1077 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1079 if (!INFONT(letter)) { //not in font, draw as space
1085 if (FFLAGS & FT_PROPORTIONAL)
1086 fp = FCHARS[letter];
1088 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1090 gr_init_bitmap (&char_bm, BM_LINEAR, 0, 0, width, FHEIGHT, width, fp);
1091 gr_bitmapm(xx,yy,&char_bm);
1103 #include "../main/inferno.h"
1104 #include "ogl_init.h"
1106 //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
1108 int pow2ize(int x);//from ogl.c
1110 int get_font_total_width(grs_font * font){
1111 if (font->ft_flags & FT_PROPORTIONAL){
1112 int i,w=0,c=font->ft_minchar;
1113 for (i=0;c<=font->ft_maxchar;i++,c++){
1114 if (font->ft_widths[i]<0)
1116 w+=font->ft_widths[i];
1120 return font->ft_w*(font->ft_maxchar-font->ft_minchar+1);
1123 void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){
1124 int nchars = font->ft_maxchar-font->ft_minchar+1;
1125 int r,x,y,nc=0,smallest=999999,smallr=-1,tries;
1126 int smallprop=10000;
1128 for (h=32;h<=256;h*=2){
1129 // h=pow2ize(font->ft_h*rows+gap*(rows-1));
1130 if (font->ft_h>h)continue;
1131 r=(h/(font->ft_h+gap));
1132 w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r);
1138 mprintf((0,"failed to fit (%ix%i, %ic)\n",w,h,nc));
1143 while(y+font->ft_h<=h){
1148 if (font->ft_flags & FT_PROPORTIONAL){
1149 if (x+font->ft_widths[nc]+gap>w)break;
1150 x+=font->ft_widths[nc++]+gap;
1152 if (x+font->ft_w+gap>w)break;
1166 mprintf((0,"fit: %ix%i %i tries\n",w,h,tries));
1168 if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32)
1189 Error("couldn't fit font?\n");
1190 mprintf((0,"using %ix%i\n",*rw,*rh));
1194 void ogl_init_font(grs_font * font){
1195 int nchars = font->ft_maxchar-font->ft_minchar+1;
1196 int i,w,h,tw,th,x,y,curx=0,cury=0;
1198 // char data[32*32*4];
1200 int gap=0;//having a gap just wastes ram, since we don't filter text textures at all.
1202 ogl_font_choose_size(font,gap,&tw,&th);
1203 data=d_malloc(tw*th);
1204 gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data);
1206 font->ft_parent_bitmap.gltexture=ogl_get_free_texture();
1208 font->ft_bitmaps=(grs_bitmap*)d_malloc( nchars * sizeof(grs_bitmap));
1209 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));
1214 for(i=0;i<nchars;i++){
1215 // s[0]=font->ft_minchar+i;
1216 // gr_get_string_size(s,&w,&h,&aw);
1217 if (font->ft_flags & FT_PROPORTIONAL)
1218 w=font->ft_widths[i];
1221 // mprintf((0,"char %i(%ix%i): ",i,w,h));
1223 mprintf((0,"grr\n"));continue;
1230 Error("font doesn't really fit (%i/%i)?\n",i,nchars);
1231 if (font->ft_flags & FT_COLOR) {
1232 if (font->ft_flags & FT_PROPORTIONAL)
1233 fp = font->ft_chars[i];
1235 fp = font->ft_data + i * w*h;
1238 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w];
1241 // gr_init_bitmap(&font->ft_bitmaps[i],BM_LINEAR,0,0,w,h,w,font->);
1243 int BitMask,bits=0,white=gr_find_closest_color(63,63,63);
1244 // if (w*h>sizeof(data))
1245 // Error("ogl_init_font: toobig\n");
1246 if (font->ft_flags & FT_PROPORTIONAL)
1247 fp = font->ft_chars[i];
1249 fp = font->ft_data + i * BITS_TO_BYTES(w)*h;
1252 for (x=0; x< w; x++ )
1260 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white;
1262 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255;
1267 gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h);
1271 if (!(font->ft_flags & FT_COLOR)) {
1272 //use GL_INTENSITY instead of GL_RGB
1273 if (ogl_intensity4_ok){
1274 font->ft_parent_bitmap.gltexture->internalformat=GL_INTENSITY4;
1275 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE;
1276 }else if (ogl_luminance4_alpha4_ok){
1277 font->ft_parent_bitmap.gltexture->internalformat=GL_LUMINANCE4_ALPHA4;
1278 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE_ALPHA;
1279 }else if (ogl_rgba2_ok){
1280 font->ft_parent_bitmap.gltexture->internalformat=GL_RGBA2;
1281 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1283 font->ft_parent_bitmap.gltexture->internalformat=ogl_rgba_format;
1284 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1287 ogl_loadbmtexture_m(&font->ft_parent_bitmap,0);
1290 int ogl_internal_string(int x, int y, char *s )
1292 ubyte * text_ptr, * next_row, * text_ptr1;
1293 int width, spacing,letter;
1295 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
1301 if (grd_curscreen->sc_canvas.cv_bitmap.bm_type != BM_OGL)
1303 while (next_row != NULL)
1305 text_ptr1 = next_row;
1308 text_ptr = text_ptr1;
1312 if (xx==0x8000) //centered
1313 xx = get_centered_x(text_ptr);
1317 if (*text_ptr == '\n' )
1319 next_row = &text_ptr[1];
1324 letter = *text_ptr-FMINCHAR;
1326 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1328 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
1329 CHECK_EMBEDDED_COLORS() else{
1336 // ogl_ubitblt(FONT->ft_bitmaps[letter].bm_w,FONT->ft_bitmaps[letter].bm_h,xx,yy,0,0,&FONT->ft_bitmaps[letter],NULL);
1337 // if (*text_ptr>='0' && *text_ptr<='9'){
1338 if (FFLAGS&FT_COLOR)
1339 gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);
1341 if (grd_curcanv->cv_bitmap.bm_type==BM_OGL)
1342 ogl_ubitmapm_c(xx,yy,&FONT->ft_bitmaps[letter],FG_COLOR);
1344 Error("ogl_internal_string: non-color string to non-ogl dest\n");
1345 // gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);//ignores color..
1358 int gr_internal_color_string(int x, int y, char *s ){
1359 return ogl_internal_string(x,y,s);
1363 int gr_string(int x, int y, char *s )
1368 Assert(FONT != NULL);
1370 if ( x == 0x8000 ) {
1371 if ( y<0 ) clipped |= 1;
1372 gr_get_string_size(s, &w, &h, &aw );
1373 // for x, since this will be centered, only look at
1375 if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1376 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1378 if ( (y+h) < 0 ) clipped |= 2;
1379 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1382 if ( (x<0) || (y<0) ) clipped |= 1;
1383 gr_get_string_size(s, &w, &h, &aw );
1384 if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1385 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1386 if ( (x+w) < 0 ) clipped |= 2;
1387 if ( (y+h) < 0 ) clipped |= 2;
1388 if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;
1389 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1393 return gr_ustring(x, y, s );
1395 if ( clipped & 2 ) {
1396 // Completely clipped...
1397 mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
1401 if ( clipped & 1 ) {
1402 // Partially clipped...
1403 //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
1406 // Partially clipped...
1409 return ogl_internal_string(x,y,s);
1412 if (FFLAGS & FT_COLOR)
1413 return gr_internal_color_string( x, y, s);
1415 if ( BG_COLOR == -1)
1416 return gr_internal_string_clipped_m( x, y, s );
1418 return gr_internal_string_clipped( x, y, s );
1421 int gr_ustring(int x, int y, char *s )
1425 return ogl_internal_string(x,y,s);
1428 if (FFLAGS & FT_COLOR) {
1430 return gr_internal_color_string(x,y,s);
1437 if ( BG_COLOR == -1)
1438 return gr_internal_string0m(x,y,s);
1440 return gr_internal_string0(x,y,s);
1443 if ( BG_COLOR == -1)
1444 return gr_internal_string2m(x,y,s);
1446 return gr_internal_string2(x,y,s);
1448 #if defined(POLY_ACC)
1450 if ( BG_COLOR == -1)
1451 return gr_internal_string5m(x,y,s);
1453 return gr_internal_string5(x,y,s);
1460 void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width )
1462 int i = 0, longest_width = 0;
1465 *string_height = FHEIGHT;
1467 *average_width = FWIDTH;
1474 // if (*s == CC_UNDERLINE)
1479 *string_height += FHEIGHT;
1485 // 1 = next byte specifies color, so skip the 1 and the color value
1488 else if (*s == CC_LSPACING) {
1489 *string_height += *(s+1)-'0';
1492 get_char_width(s[0],s[1],&width,&spacing);
1494 *string_width += spacing;
1496 if (*string_width > longest_width)
1497 longest_width = *string_width;
1504 *string_width = longest_width;
1508 int gr_uprintf( int x, int y, char * format, ... )
1513 va_start(args, format );
1514 vsprintf(buffer,format,args);
1515 return gr_ustring( x, y, buffer );
1518 int gr_printf( int x, int y, char * format, ... )
1523 va_start(args, format );
1524 vsprintf(buffer,format,args);
1525 return gr_string( x, y, buffer );
1528 void gr_close_font( grs_font * font )
1535 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=font;fontnum++);
1536 Assert(fontnum<MAX_OPEN_FONTS); //did we find slot?
1538 open_font[fontnum].ptr = NULL;
1540 if ( font->ft_chars )
1541 d_free( font->ft_chars );
1542 d_free( font->oldfont );
1544 if (font->ft_bitmaps)
1545 d_free( font->ft_bitmaps );
1546 gr_free_bitmap_data(&font->ft_parent_bitmap);
1547 // ogl_freebmtexture(&font->ft_parent_bitmap);
1554 //remap (by re-reading) all the color fonts
1555 void gr_remap_color_fonts()
1559 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1562 font = open_font[fontnum].ptr;
1564 if (font && (font->ft_flags & FT_COLOR))
1565 gr_remap_font(font,open_font[fontnum].filename);
1569 void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq );
1570 void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count );
1572 #pragma aux decode_data_asm parm [esi] [ecx] [edi] [ebx] modify exact [esi edi eax ebx ecx] = \
1576 "inc dword ptr [ebx+eax*4]" \
1577 "mov al,[edi+eax]" \
1585 grs_font * gr_init_font( char * fontname )
1587 static int first_time=1;
1591 unsigned char * ptr;
1595 int32_t datasize; //size up to (but not including) palette
1599 for (i=0;i<MAX_OPEN_FONTS;i++)
1600 open_font[i].ptr = NULL;
1604 //find free font slot
1605 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=NULL;fontnum++);
1606 Assert(fontnum<MAX_OPEN_FONTS); //did we find one?
1608 strncpy(open_font[fontnum].filename,fontname,FILENAME_LEN);
1610 fontfile = cfopen(fontname, "rb");
1613 Error( "Can't open font file %s", fontname );
1615 cfread(&file_id,sizeof(file_id),1,fontfile);
1616 file_id=swapint(file_id);
1617 cfread(&datasize,sizeof(datasize),1,fontfile);
1618 datasize=swapint(datasize);
1620 if (file_id != MAKE_SIG('N','F','S','P'))
1621 Error( "File %s is not a font file", fontname );
1623 font = (old_grs_font *) d_malloc(datasize);
1624 newfont = (grs_font *) d_malloc(sizeof(grs_font));
1625 newfont->oldfont=font;
1627 open_font[fontnum].ptr = newfont;
1629 cfread(font,1,datasize,fontfile);
1631 newfont->ft_flags=swapint(font->ft_flags);
1632 newfont->ft_w=swapshort(font->ft_w);
1633 newfont->ft_h=swapshort(font->ft_h);
1634 newfont->ft_baseline=swapshort(font->ft_baseline);
1635 newfont->ft_maxchar=font->ft_maxchar;
1636 newfont->ft_minchar=font->ft_minchar;
1637 newfont->ft_bytewidth=swapshort(font->ft_bytewidth);
1639 nchars = newfont->ft_maxchar-newfont->ft_minchar+1;
1641 if (newfont->ft_flags & FT_PROPORTIONAL) {
1643 newfont->ft_widths = (short *) (swapint(font->ft_widths) + ((ubyte *) font));
1644 newfont->ft_data = (swapint(font->ft_data)) + ((ubyte *) font);
1645 newfont->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1647 ptr = newfont->ft_data;
1649 for (i=0; i< nchars; i++ ) {
1650 newfont->ft_chars[i] = ptr;
1651 if (newfont->ft_flags & FT_COLOR)
1652 ptr += newfont->ft_widths[i] * newfont->ft_h;
1654 ptr += BITS_TO_BYTES(newfont->ft_widths[i]) * newfont->ft_h;
1659 newfont->ft_data = ((unsigned char *) font) + sizeof(*font);
1660 newfont->ft_chars = NULL;
1661 newfont->ft_widths = NULL;
1663 ptr = newfont->ft_data + (nchars * newfont->ft_w * newfont->ft_h);
1666 if (newfont->ft_flags & FT_KERNED)
1667 newfont->ft_kerndata = swapint(font->ft_kerndata) + ((ubyte *) font);
1669 if (newfont->ft_flags & FT_COLOR) { //remap palette
1670 ubyte palette[256*3];
1671 ubyte colormap[256];
1674 cfread(palette,3,256,fontfile); //read the palette
1676 #ifdef MACINTOSH // swap the first and last palette entries (black and white)
1681 for (i = 0; i < 3; i++) {
1683 palette[i] = palette[765+i];
1687 // we also need to swap the data entries as well. black is white and white is black
1689 for (i = 0; i < ptr-newfont->ft_data; i++) {
1690 if (newfont->ft_data[i] == 0)
1691 newfont->ft_data[i] = 255;
1692 else if (newfont->ft_data[i] == 255)
1693 newfont->ft_data[i] = 0;
1699 build_colormap_good( (ubyte *)&palette, colormap, freq );
1701 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // chaged from colormap[255] = 255 to this for macintosh
1703 decode_data_asm(newfont->ft_data, ptr-newfont->ft_data, colormap, freq );
1709 // memcpy(newfont,font,(ubyte*)&newfont->oldfont-(ubyte*)newfont);//fill in newfont data from oldfont struct
1710 // mprintf((0,"%i %i %i\n",sizeof(grs_font),sizeof(old_grs_font),(ubyte*)&newfont->oldfont-(ubyte*)newfont));
1720 char tests[]="abcdefghij1234.A";
1721 gr_get_string_size(tests,&x,&y,&aw);
1722 // newfont->ft_aw=x/(float)strlen(tests);
1726 ogl_init_font(newfont);
1733 //remap a font by re-reading its data & palette
1734 void gr_remap_font( grs_font *font, char * fontname )
1740 int32_t datasize; //size up to (but not including) palette
1743 if (! (font->ft_flags & FT_COLOR))
1746 fontfile = cfopen(fontname, "rb");
1749 Error( "Can't open font file %s", fontname );
1751 file_id = cfile_read_int(fontfile);
1752 datasize = cfile_read_int(fontfile);
1754 if (file_id != MAKE_SIG('N','F','S','P'))
1755 Error( "File %s is not a font file", fontname );
1757 nchars = font->ft_maxchar-font->ft_minchar+1;
1759 //compute data length
1761 if (font->ft_flags & FT_PROPORTIONAL) {
1763 for (i=0; i< nchars; i++ ) {
1764 if (font->ft_flags & FT_COLOR)
1765 data_len += font->ft_widths[i] * font->ft_h;
1767 data_len += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1771 data_len = nchars * font->ft_w * font->ft_h;
1773 cfread(font->oldfont, 1, datasize, fontfile); //read raw data
1775 if (font->ft_flags & FT_COLOR) { //remap palette
1776 ubyte palette[256*3];
1777 ubyte colormap[256];
1780 cfseek(fontfile,-sizeof(palette),SEEK_END);
1782 cfread(palette,3,256,fontfile); //read the palette
1784 #ifdef MACINTOSH // swap the first and last palette entries (black and white)
1789 for (i = 0; i < 3; i++) {
1791 palette[i] = palette[765+i];
1795 // we also need to swap the data entries as well. black is white and white is black
1797 for (i = 0; i < data_len; i++) {
1798 if (font->ft_data[i] == 0)
1799 font->ft_data[i] = 255;
1800 else if (font->ft_data[i] == 255)
1801 font->ft_data[i] = 0;
1807 build_colormap_good( (ubyte *)&palette, colormap, freq );
1809 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255;
1811 decode_data_asm(font->ft_data, data_len, colormap, freq );
1818 if (font->ft_bitmaps)
1819 d_free( font->ft_bitmaps );
1820 gr_free_bitmap_data(&font->ft_parent_bitmap);
1821 // ogl_freebmtexture(&font->ft_parent_bitmap);
1823 ogl_init_font(font);
1828 void gr_set_fontcolor( int fg, int bg )
1834 void gr_set_curfont( grs_font * new )
1840 int gr_internal_string_clipped(int x, int y, char *s )
1843 char * text_ptr, * next_row, * text_ptr1;
1844 int r, BitMask, i, bits, width, spacing, letter, underline;
1851 while (next_row != NULL )
1853 text_ptr1 = next_row;
1857 if (x==0x8000) //centered
1858 x = get_centered_x(text_ptr1);
1862 for (r=0; r<FHEIGHT; r++) {
1863 text_ptr = text_ptr1;
1867 if (*text_ptr == '\n' ) {
1868 next_row = &text_ptr[1];
1872 if (*text_ptr == CC_COLOR) {
1873 FG_COLOR = *(text_ptr+1);
1878 if (*text_ptr == CC_LSPACING) {
1879 Int3(); // Warning: skip lines not supported for clipped strings.
1885 if (*text_ptr == CC_UNDERLINE ) {
1886 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1891 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1893 letter = *text_ptr-FMINCHAR;
1895 if (!INFONT(letter)) { //not in font, draw as space
1901 if (FFLAGS & FT_PROPORTIONAL)
1902 fp = FCHARS[letter];
1904 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1907 for (i=0; i< width; i++ ) {
1908 gr_setcolor(FG_COLOR);
1912 fp += BITS_TO_BYTES(width)*r;
1916 for (i=0; i< width; i++ ) {
1922 gr_setcolor(FG_COLOR);
1924 gr_setcolor(BG_COLOR);
1930 x += spacing-width; //for kerning
1940 int gr_internal_string_clipped_m(int x, int y, char *s )
1943 char * text_ptr, * next_row, * text_ptr1;
1944 int r, BitMask, i, bits, width, spacing, letter, underline;
1951 while (next_row != NULL )
1953 text_ptr1 = next_row;
1957 if (x==0x8000) //centered
1958 x = get_centered_x(text_ptr1);
1962 for (r=0; r<FHEIGHT; r++) {
1965 text_ptr = text_ptr1;
1968 if (*text_ptr == '\n' ) {
1969 next_row = &text_ptr[1];
1973 if (*text_ptr == CC_COLOR) {
1974 FG_COLOR = *(text_ptr+1);
1979 if (*text_ptr == CC_LSPACING) {
1980 Int3(); // Warning: skip lines not supported for clipped strings.
1986 if (*text_ptr == CC_UNDERLINE ) {
1987 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1992 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1994 letter = *text_ptr-FMINCHAR;
1996 if (!INFONT(letter)) { //not in font, draw as space
2002 if (FFLAGS & FT_PROPORTIONAL)
2003 fp = FCHARS[letter];
2005 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
2008 for (i=0; i< width; i++ ) {
2009 gr_setcolor(FG_COLOR);
2013 fp += BITS_TO_BYTES(width)*r;
2017 for (i=0; i< width; i++ ) {
2022 if (bits & BitMask) {
2023 gr_setcolor(FG_COLOR);
2032 x += spacing-width; //for kerning