1 /* $Id: font.c,v 1.17 2002-08-06 09:28:00 btb 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];
59 //list of open fonts, for use (for now) for palette remapping
60 openfont open_font[MAX_OPEN_FONTS];
62 #define FONT grd_curcanv->cv_font
63 #define FG_COLOR grd_curcanv->cv_font_fg_color
64 #define BG_COLOR grd_curcanv->cv_font_bg_color
65 #define FWIDTH FONT->ft_w
66 #define FHEIGHT FONT->ft_h
67 #define FBASELINE FONT->ft_baseline
68 #define FFLAGS FONT->ft_flags
69 #define FMINCHAR FONT->ft_minchar
70 #define FMAXCHAR FONT->ft_maxchar
71 #define FDATA FONT->ft_data
72 #define FCHARS FONT->ft_chars
73 #define FWIDTHS FONT->ft_widths
75 #define BITS_TO_BYTES(x) (((x)+7)>>3)
77 int gr_internal_string_clipped(int x, int y, char *s );
78 int gr_internal_string_clipped_m(int x, int y, char *s );
80 ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second)
82 ubyte *p=font->ft_kerndata;
85 if (p[0]==first && p[1]==second)
93 //takes the character AFTER being offset into font
94 #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
96 //takes the character BEFORE being offset into current font
97 void get_char_width(ubyte c,ubyte c2,int *width,int *spacing)
103 if (!INFONT(letter)) { //not in font, draw as space
105 if (FFLAGS & FT_PROPORTIONAL)
112 if (FFLAGS & FT_PROPORTIONAL)
113 *width = FWIDTHS[letter];
119 if (FFLAGS & FT_KERNED) {
122 if (!(c2==0 || c2=='\n')) {
125 letter2 = c2-FMINCHAR;
127 if (INFONT(letter2)) {
129 p = find_kern_entry(FONT,(ubyte)letter,letter2);
138 int get_centered_x(char *s)
142 for (w=0;*s!=0 && *s!='\n';s++) {
146 continue;//skip color codes.
148 get_char_width(s[0],s[1],&w2,&s2);
152 return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
155 //hack to allow color codes to be embedded in strings -MPM
156 //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string.
157 //function must already have orig_color var set (or they could be passed as args...)
158 //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain
159 int gr_message_color_level=1;
160 #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x03)) { \
163 if (gr_message_color_level >= *(text_ptr-1)) \
164 FG_COLOR = *text_ptr - 1; \
168 else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \
169 if (gr_message_color_level >= *text_ptr - 3) \
170 FG_COLOR=orig_color; \
174 int gr_internal_string0(int x, int y, char *s )
177 ubyte * text_ptr, * next_row, * text_ptr1;
178 int r, BitMask, i, bits, width, spacing, letter, underline;
181 unsigned int VideoOffset, VideoOffset1;
185 VideoOffset1 = y * ROWSIZE + x;
189 while (next_row != NULL )
191 text_ptr1 = next_row;
194 if (x==0x8000) { //centered
195 int xx = get_centered_x(text_ptr1);
196 VideoOffset1 = y * ROWSIZE + xx;
199 for (r=0; r<FHEIGHT; r++)
202 text_ptr = text_ptr1;
204 VideoOffset = VideoOffset1;
208 if (*text_ptr == '\n' )
210 next_row = &text_ptr[1];
214 if (*text_ptr == CC_COLOR) {
215 FG_COLOR = *(text_ptr+1);
220 if (*text_ptr == CC_LSPACING) {
221 skip_lines = *(text_ptr+1) - '0';
227 if (*text_ptr == CC_UNDERLINE )
229 if ((r==FBASELINE+2) || (r==FBASELINE+3))
234 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
236 letter = *text_ptr-FMINCHAR;
238 if (!INFONT(letter)) { //not in font, draw as space
239 VideoOffset += spacing;
244 if (FFLAGS & FT_PROPORTIONAL)
247 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
250 for (i=0; i< width; i++ )
251 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
254 fp += BITS_TO_BYTES(width)*r;
258 for (i=0; i< width; i++ )
266 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
268 DATA[VideoOffset++] = (unsigned char) BG_COLOR;
273 VideoOffset += spacing-width; //for kerning
278 VideoOffset1 += ROWSIZE; y++;
282 VideoOffset1 += ROWSIZE * skip_lines;
288 int gr_internal_string0m(int x, int y, char *s )
291 ubyte * text_ptr, * next_row, * text_ptr1;
292 int r, BitMask, i, bits, width, spacing, letter, underline;
295 unsigned int VideoOffset, VideoOffset1;
297 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
301 VideoOffset1 = y * ROWSIZE + x;
305 while (next_row != NULL )
307 text_ptr1 = next_row;
310 if (x==0x8000) { //centered
311 int xx = get_centered_x(text_ptr1);
312 VideoOffset1 = y * ROWSIZE + xx;
315 for (r=0; r<FHEIGHT; r++)
318 text_ptr = text_ptr1;
320 VideoOffset = VideoOffset1;
324 if (*text_ptr == '\n' )
326 next_row = &text_ptr[1];
330 if (*text_ptr == CC_COLOR) {
331 FG_COLOR = *(text_ptr+1);
336 if (*text_ptr == CC_LSPACING) {
337 skip_lines = *(text_ptr+1) - '0';
343 if (*text_ptr == CC_UNDERLINE )
345 if ((r==FBASELINE+2) || (r==FBASELINE+3))
350 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
352 letter = *text_ptr-FMINCHAR;
354 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
355 CHECK_EMBEDDED_COLORS() else{
356 VideoOffset += spacing;
362 if (FFLAGS & FT_PROPORTIONAL)
365 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
368 for (i=0; i< width; i++ )
369 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
372 fp += BITS_TO_BYTES(width)*r;
376 for (i=0; i< width; i++ )
384 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
392 VideoOffset += spacing-width;
395 VideoOffset1 += ROWSIZE;
399 VideoOffset1 += ROWSIZE * skip_lines;
406 int gr_internal_string2(int x, int y, char *s )
409 ubyte * text_ptr, * next_row, * text_ptr1;
410 int r, BitMask, i, bits, width, spacing, letter, underline;
411 int page_switched, skip_lines = 0;
413 unsigned int VideoOffset, VideoOffset1;
415 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
419 gr_vesa_setpage(VideoOffset1 >> 16);
421 VideoOffset1 &= 0xFFFF;
425 while (next_row != NULL )
427 text_ptr1 = next_row;
430 if (x==0x8000) { //centered
431 int xx = get_centered_x(text_ptr1);
432 VideoOffset1 = y * ROWSIZE + xx;
433 gr_vesa_setpage(VideoOffset1 >> 16);
434 VideoOffset1 &= 0xFFFF;
437 for (r=0; r<FHEIGHT; r++)
439 text_ptr = text_ptr1;
441 VideoOffset = VideoOffset1;
447 if (*text_ptr == '\n' )
449 next_row = &text_ptr[1];
453 if (*text_ptr == CC_COLOR) {
454 FG_COLOR = *(text_ptr+1);
459 if (*text_ptr == CC_LSPACING) {
460 skip_lines = *(text_ptr+1) - '0';
466 if (*text_ptr == CC_UNDERLINE )
468 if ((r==FBASELINE+2) || (r==FBASELINE+3))
473 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
475 Assert(width==spacing); //no kerning support here
477 letter = *text_ptr-FMINCHAR;
479 if (!INFONT(letter)) { //not in font, draw as space
480 VideoOffset += spacing;
485 if (FFLAGS & FT_PROPORTIONAL)
488 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
492 if ( VideoOffset+width > 0xFFFF )
494 for (i=0; i< width; i++ )
496 gr_video_memory[VideoOffset++] = FG_COLOR;
498 if (VideoOffset > 0xFFFF )
500 VideoOffset -= 0xFFFF + 1;
508 for (i=0; i< width; i++ )
509 gr_video_memory[VideoOffset++] = FG_COLOR;
518 fp += BITS_TO_BYTES(width)*r;
522 if ( VideoOffset+width > 0xFFFF )
524 for (i=0; i< width; i++ )
532 gr_video_memory[VideoOffset++] = FG_COLOR;
534 gr_video_memory[VideoOffset++] = BG_COLOR;
538 if (VideoOffset > 0xFFFF )
540 VideoOffset -= 0xFFFF + 1;
552 if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR;
553 else gr_video_memory[VideoOffset+0] = BG_COLOR;
555 if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR;
556 else gr_video_memory[VideoOffset+1] = BG_COLOR;
558 if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR;
559 else gr_video_memory[VideoOffset+2] = BG_COLOR;
561 if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR;
562 else gr_video_memory[VideoOffset+3] = BG_COLOR;
564 if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR;
565 else gr_video_memory[VideoOffset+4] = BG_COLOR;
567 if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR;
568 else gr_video_memory[VideoOffset+5] = BG_COLOR;
570 if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR;
571 else gr_video_memory[VideoOffset+6] = BG_COLOR;
573 if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR;
574 else gr_video_memory[VideoOffset+7] = BG_COLOR;
578 for (i=0; i< width/2 ; i++ )
586 gr_video_memory[VideoOffset++] = FG_COLOR;
588 gr_video_memory[VideoOffset++] = BG_COLOR;
600 gr_video_memory[VideoOffset++] = FG_COLOR;
602 gr_video_memory[VideoOffset++] = BG_COLOR;
612 VideoOffset1 += ROWSIZE;
614 if (VideoOffset1 > 0xFFFF ) {
615 VideoOffset1 -= 0xFFFF + 1;
622 VideoOffset1 += ROWSIZE * skip_lines;
628 int gr_internal_string2m(int x, int y, char *s )
631 char * text_ptr, * next_row, * text_ptr1;
632 int r, BitMask, i, bits, width, spacing, letter, underline;
633 int page_switched, skip_lines = 0;
635 unsigned int VideoOffset, VideoOffset1;
637 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
639 gr_vesa_setpage(VideoOffset1 >> 16);
641 VideoOffset1 &= 0xFFFF;
645 while (next_row != NULL )
647 text_ptr1 = next_row;
650 if (x==0x8000) { //centered
651 int xx = get_centered_x(text_ptr1);
652 VideoOffset1 = y * ROWSIZE + xx;
653 gr_vesa_setpage(VideoOffset1 >> 16);
654 VideoOffset1 &= 0xFFFF;
657 for (r=0; r<FHEIGHT; r++)
659 text_ptr = text_ptr1;
661 VideoOffset = VideoOffset1;
667 if (*text_ptr == '\n' )
669 next_row = &text_ptr[1];
673 if (*text_ptr == CC_COLOR) {
674 FG_COLOR = *(text_ptr+1);
679 if (*text_ptr == CC_LSPACING) {
680 skip_lines = *(text_ptr+1) - '0';
686 if (*text_ptr == CC_UNDERLINE )
688 if ((r==FBASELINE+2) || (r==FBASELINE+3))
693 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
695 letter = *text_ptr-FMINCHAR;
697 if (!INFONT(letter)) { //not in font, draw as space
698 VideoOffset += width;
703 if (FFLAGS & FT_PROPORTIONAL)
706 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
710 if ( VideoOffset+width > 0xFFFF )
712 for (i=0; i< width; i++ )
714 gr_video_memory[VideoOffset++] = FG_COLOR;
716 if (VideoOffset > 0xFFFF )
718 VideoOffset -= 0xFFFF + 1;
726 for (i=0; i< width; i++ )
727 gr_video_memory[VideoOffset++] = FG_COLOR;
732 fp += BITS_TO_BYTES(width)*r;
736 if ( VideoOffset+width > 0xFFFF )
738 for (i=0; i< width; i++ )
746 gr_video_memory[VideoOffset++] = FG_COLOR;
752 if (VideoOffset > 0xFFFF )
754 VideoOffset -= 0xFFFF + 1;
761 for (i=0; i< width; i++ )
769 gr_video_memory[VideoOffset++] = FG_COLOR;
778 VideoOffset += spacing-width;
782 VideoOffset1 += ROWSIZE;
784 if (VideoOffset1 > 0xFFFF ) {
785 VideoOffset1 -= 0xFFFF + 1;
792 VideoOffset1 += ROWSIZE * skip_lines;
800 #if defined(POLY_ACC)
801 int gr_internal_string5(int x, int y, char *s )
804 ubyte * text_ptr, * next_row, * text_ptr1;
805 int r, BitMask, i, bits, width, spacing, letter, underline;
808 unsigned int VideoOffset, VideoOffset1;
811 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
815 while (next_row != NULL )
817 text_ptr1 = next_row;
820 if (x==0x8000) { //centered
821 int xx = get_centered_x(text_ptr1);
822 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
825 for (r=0; r<FHEIGHT; r++)
828 text_ptr = text_ptr1;
830 VideoOffset = VideoOffset1;
834 if (*text_ptr == '\n' )
836 next_row = &text_ptr[1];
840 if (*text_ptr == CC_COLOR) {
841 FG_COLOR = *(text_ptr+1);
846 if (*text_ptr == CC_LSPACING) {
847 skip_lines = *(text_ptr+1) - '0';
853 if (*text_ptr == CC_UNDERLINE )
855 if ((r==FBASELINE+2) || (r==FBASELINE+3))
860 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
862 letter = *text_ptr-FMINCHAR;
864 if (!INFONT(letter)) { //not in font, draw as space
865 VideoOffset += spacing * PA_BPP;
870 if (FFLAGS & FT_PROPORTIONAL)
873 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
876 for (i=0; i< width; i++ )
877 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
880 fp += BITS_TO_BYTES(width)*r;
884 for (i=0; i< width; i++ )
892 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
894 { *(short *)(DATA + VideoOffset) = pa_clut[BG_COLOR]; VideoOffset += PA_BPP; }
899 VideoOffset += PA_BPP * (spacing-width); //for kerning
904 VideoOffset1 += ROWSIZE; y++;
908 VideoOffset1 += ROWSIZE * skip_lines;
914 int gr_internal_string5m(int x, int y, char *s )
917 ubyte * text_ptr, * next_row, * text_ptr1;
918 int r, BitMask, i, bits, width, spacing, letter, underline;
921 unsigned int VideoOffset, VideoOffset1;
924 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
928 while (next_row != NULL )
930 text_ptr1 = next_row;
933 if (x==0x8000) { //centered
934 int xx = get_centered_x(text_ptr1);
935 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
938 for (r=0; r<FHEIGHT; r++)
941 text_ptr = text_ptr1;
943 VideoOffset = VideoOffset1;
947 if (*text_ptr == '\n' )
949 next_row = &text_ptr[1];
953 if (*text_ptr == CC_COLOR) {
954 FG_COLOR = *(text_ptr+1);
959 if (*text_ptr == CC_LSPACING) {
960 skip_lines = *(text_ptr+1) - '0';
966 if (*text_ptr == CC_UNDERLINE )
968 if ((r==FBASELINE+2) || (r==FBASELINE+3))
973 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
975 letter = *text_ptr-FMINCHAR;
977 if (!INFONT(letter)) { //not in font, draw as space
978 VideoOffset += spacing * PA_BPP;
983 if (FFLAGS & FT_PROPORTIONAL)
986 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
989 for (i=0; i< width; i++ )
990 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
993 fp += BITS_TO_BYTES(width)*r;
997 for (i=0; i< width; i++ )
1005 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
1007 VideoOffset += PA_BPP;
1013 VideoOffset += PA_BPP * (spacing-width);
1016 VideoOffset1 += ROWSIZE; y++;
1019 VideoOffset1 += ROWSIZE * skip_lines;
1027 //a bitmap for the character
1028 grs_bitmap char_bm = {
1031 BM_FLAG_TRANSPARENT, //flags
1034 #ifdef BITMAP_SELECTOR
1041 int gr_internal_color_string(int x, int y, char *s )
1044 ubyte * text_ptr, * next_row, * text_ptr1;
1045 int width, spacing,letter;
1048 char_bm.bm_h = FHEIGHT; //set height for chars of this font
1055 while (next_row != NULL)
1057 text_ptr1 = next_row;
1060 text_ptr = text_ptr1;
1064 if (xx==0x8000) //centered
1065 xx = get_centered_x(text_ptr);
1069 if (*text_ptr == '\n' )
1071 next_row = &text_ptr[1];
1076 letter = *text_ptr-FMINCHAR;
1078 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1080 if (!INFONT(letter)) { //not in font, draw as space
1086 if (FFLAGS & FT_PROPORTIONAL)
1087 fp = FCHARS[letter];
1089 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1091 gr_init_bitmap (&char_bm, BM_LINEAR, 0, 0, width, FHEIGHT, width, fp);
1092 gr_bitmapm(xx,yy,&char_bm);
1104 #include "../main/inferno.h"
1105 #include "ogl_init.h"
1107 //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
1109 int pow2ize(int x);//from ogl.c
1111 int get_font_total_width(grs_font * font){
1112 if (font->ft_flags & FT_PROPORTIONAL){
1113 int i,w=0,c=font->ft_minchar;
1114 for (i=0;c<=font->ft_maxchar;i++,c++){
1115 if (font->ft_widths[i]<0)
1117 w+=font->ft_widths[i];
1121 return font->ft_w*(font->ft_maxchar-font->ft_minchar+1);
1124 void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){
1125 int nchars = font->ft_maxchar-font->ft_minchar+1;
1126 int r,x,y,nc=0,smallest=999999,smallr=-1,tries;
1127 int smallprop=10000;
1129 for (h=32;h<=256;h*=2){
1130 // h=pow2ize(font->ft_h*rows+gap*(rows-1));
1131 if (font->ft_h>h)continue;
1132 r=(h/(font->ft_h+gap));
1133 w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r);
1139 mprintf((0,"failed to fit (%ix%i, %ic)\n",w,h,nc));
1144 while(y+font->ft_h<=h){
1149 if (font->ft_flags & FT_PROPORTIONAL){
1150 if (x+font->ft_widths[nc]+gap>w)break;
1151 x+=font->ft_widths[nc++]+gap;
1153 if (x+font->ft_w+gap>w)break;
1167 mprintf((0,"fit: %ix%i %i tries\n",w,h,tries));
1169 if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32)
1190 Error("couldn't fit font?\n");
1191 mprintf((0,"using %ix%i\n",*rw,*rh));
1195 void ogl_init_font(grs_font * font){
1196 int nchars = font->ft_maxchar-font->ft_minchar+1;
1197 int i,w,h,tw,th,x,y,curx=0,cury=0;
1199 // char data[32*32*4];
1201 int gap=0;//having a gap just wastes ram, since we don't filter text textures at all.
1203 ogl_font_choose_size(font,gap,&tw,&th);
1204 data=d_malloc(tw*th);
1205 gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data);
1207 font->ft_parent_bitmap.gltexture=ogl_get_free_texture();
1209 font->ft_bitmaps=(grs_bitmap*)d_malloc( nchars * sizeof(grs_bitmap));
1210 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));
1215 for(i=0;i<nchars;i++){
1216 // s[0]=font->ft_minchar+i;
1217 // gr_get_string_size(s,&w,&h,&aw);
1218 if (font->ft_flags & FT_PROPORTIONAL)
1219 w=font->ft_widths[i];
1222 // mprintf((0,"char %i(%ix%i): ",i,w,h));
1224 mprintf((0,"grr\n"));continue;
1231 Error("font doesn't really fit (%i/%i)?\n",i,nchars);
1232 if (font->ft_flags & FT_COLOR) {
1233 if (font->ft_flags & FT_PROPORTIONAL)
1234 fp = font->ft_chars[i];
1236 fp = font->ft_data + i * w*h;
1239 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w];
1242 // gr_init_bitmap(&font->ft_bitmaps[i],BM_LINEAR,0,0,w,h,w,font->);
1244 int BitMask,bits=0,white=gr_find_closest_color(63,63,63);
1245 // if (w*h>sizeof(data))
1246 // Error("ogl_init_font: toobig\n");
1247 if (font->ft_flags & FT_PROPORTIONAL)
1248 fp = font->ft_chars[i];
1250 fp = font->ft_data + i * BITS_TO_BYTES(w)*h;
1253 for (x=0; x< w; x++ )
1261 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white;
1263 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255;
1268 gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h);
1272 if (!(font->ft_flags & FT_COLOR)) {
1273 //use GL_INTENSITY instead of GL_RGB
1274 if (ogl_intensity4_ok){
1275 font->ft_parent_bitmap.gltexture->internalformat=GL_INTENSITY4;
1276 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE;
1277 }else if (ogl_luminance4_alpha4_ok){
1278 font->ft_parent_bitmap.gltexture->internalformat=GL_LUMINANCE4_ALPHA4;
1279 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE_ALPHA;
1280 }else if (ogl_rgba2_ok){
1281 font->ft_parent_bitmap.gltexture->internalformat=GL_RGBA2;
1282 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1284 font->ft_parent_bitmap.gltexture->internalformat=ogl_rgba_format;
1285 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1288 ogl_loadbmtexture_m(&font->ft_parent_bitmap,0);
1291 int ogl_internal_string(int x, int y, char *s )
1293 ubyte * text_ptr, * next_row, * text_ptr1;
1294 int width, spacing,letter;
1296 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
1302 if (grd_curscreen->sc_canvas.cv_bitmap.bm_type != BM_OGL)
1304 while (next_row != NULL)
1306 text_ptr1 = next_row;
1309 text_ptr = text_ptr1;
1313 if (xx==0x8000) //centered
1314 xx = get_centered_x(text_ptr);
1318 if (*text_ptr == '\n' )
1320 next_row = &text_ptr[1];
1325 letter = *text_ptr-FMINCHAR;
1327 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1329 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
1330 CHECK_EMBEDDED_COLORS() else{
1337 // ogl_ubitblt(FONT->ft_bitmaps[letter].bm_w,FONT->ft_bitmaps[letter].bm_h,xx,yy,0,0,&FONT->ft_bitmaps[letter],NULL);
1338 // if (*text_ptr>='0' && *text_ptr<='9'){
1339 if (FFLAGS&FT_COLOR)
1340 gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);
1342 if (grd_curcanv->cv_bitmap.bm_type==BM_OGL)
1343 ogl_ubitmapm_c(xx,yy,&FONT->ft_bitmaps[letter],FG_COLOR);
1345 Error("ogl_internal_string: non-color string to non-ogl dest\n");
1346 // gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);//ignores color..
1359 int gr_internal_color_string(int x, int y, char *s ){
1360 return ogl_internal_string(x,y,s);
1364 int gr_string(int x, int y, char *s )
1369 Assert(FONT != NULL);
1371 if ( x == 0x8000 ) {
1372 if ( y<0 ) clipped |= 1;
1373 gr_get_string_size(s, &w, &h, &aw );
1374 // for x, since this will be centered, only look at
1376 if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1377 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1379 if ( (y+h) < 0 ) clipped |= 2;
1380 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1383 if ( (x<0) || (y<0) ) clipped |= 1;
1384 gr_get_string_size(s, &w, &h, &aw );
1385 if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1386 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1387 if ( (x+w) < 0 ) clipped |= 2;
1388 if ( (y+h) < 0 ) clipped |= 2;
1389 if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;
1390 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1394 return gr_ustring(x, y, s );
1396 if ( clipped & 2 ) {
1397 // Completely clipped...
1398 mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
1402 if ( clipped & 1 ) {
1403 // Partially clipped...
1404 //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
1407 // Partially clipped...
1410 return ogl_internal_string(x,y,s);
1413 if (FFLAGS & FT_COLOR)
1414 return gr_internal_color_string( x, y, s);
1416 if ( BG_COLOR == -1)
1417 return gr_internal_string_clipped_m( x, y, s );
1419 return gr_internal_string_clipped( x, y, s );
1422 int gr_ustring(int x, int y, char *s )
1426 return ogl_internal_string(x,y,s);
1429 if (FFLAGS & FT_COLOR) {
1431 return gr_internal_color_string(x,y,s);
1438 if ( BG_COLOR == -1)
1439 return gr_internal_string0m(x,y,s);
1441 return gr_internal_string0(x,y,s);
1444 if ( BG_COLOR == -1)
1445 return gr_internal_string2m(x,y,s);
1447 return gr_internal_string2(x,y,s);
1449 #if defined(POLY_ACC)
1451 if ( BG_COLOR == -1)
1452 return gr_internal_string5m(x,y,s);
1454 return gr_internal_string5(x,y,s);
1461 void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width )
1463 int i = 0, longest_width = 0;
1466 *string_height = FHEIGHT;
1468 *average_width = FWIDTH;
1475 // if (*s == CC_UNDERLINE)
1480 *string_height += FHEIGHT;
1486 // 1 = next byte specifies color, so skip the 1 and the color value
1489 else if (*s == CC_LSPACING) {
1490 *string_height += *(s+1)-'0';
1493 get_char_width(s[0],s[1],&width,&spacing);
1495 *string_width += spacing;
1497 if (*string_width > longest_width)
1498 longest_width = *string_width;
1505 *string_width = longest_width;
1509 int gr_uprintf( int x, int y, char * format, ... )
1514 va_start(args, format );
1515 vsprintf(buffer,format,args);
1516 return gr_ustring( x, y, buffer );
1519 int gr_printf( int x, int y, char * format, ... )
1524 va_start(args, format );
1525 vsprintf(buffer,format,args);
1526 return gr_string( x, y, buffer );
1529 void gr_close_font( grs_font * font )
1537 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=font;fontnum++);
1538 Assert(fontnum<MAX_OPEN_FONTS); //did we find slot?
1540 font_data = open_font[fontnum].dataptr;
1541 d_free( font_data );
1543 open_font[fontnum].ptr = NULL;
1544 open_font[fontnum].dataptr = NULL;
1546 if ( font->ft_chars )
1547 d_free( font->ft_chars );
1549 if (font->ft_bitmaps)
1550 d_free( font->ft_bitmaps );
1551 gr_free_bitmap_data(&font->ft_parent_bitmap);
1552 // ogl_freebmtexture(&font->ft_parent_bitmap);
1560 //remap (by re-reading) all the color fonts
1561 void gr_remap_color_fonts()
1565 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1568 font = open_font[fontnum].ptr;
1570 if (font && (font->ft_flags & FT_COLOR))
1571 gr_remap_font(font, open_font[fontnum].filename, open_font[fontnum].dataptr);
1575 void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq );
1576 void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count );
1578 #pragma aux decode_data_asm parm [esi] [ecx] [edi] [ebx] modify exact [esi edi eax ebx ecx] = \
1582 "inc dword ptr [ebx+eax*4]" \
1583 "mov al,[edi+eax]" \
1592 * reads a grs_font structure from a CFILE
1594 void grs_font_read(grs_font *gf, CFILE *fp)
1596 gf->ft_w = cfile_read_short(fp);
1597 gf->ft_h = cfile_read_short(fp);
1598 gf->ft_flags = cfile_read_short(fp);
1599 gf->ft_baseline = cfile_read_short(fp);
1600 gf->ft_minchar = cfile_read_byte(fp);
1601 gf->ft_maxchar = cfile_read_byte(fp);
1602 gf->ft_bytewidth = cfile_read_short(fp);
1603 gf->ft_data = (ubyte *)cfile_read_int(fp);
1604 gf->ft_chars = (ubyte **)cfile_read_int(fp);
1605 gf->ft_widths = (short *)cfile_read_int(fp);
1606 gf->ft_kerndata = (ubyte *)cfile_read_int(fp);
1609 grs_font * gr_init_font( char * fontname )
1611 static int first_time=1;
1615 unsigned char * ptr;
1619 int datasize; //size up to (but not including) palette
1623 for (i=0;i<MAX_OPEN_FONTS;i++)
1624 open_font[i].ptr = NULL;
1625 open_font[i].dataptr = NULL;
1629 //find free font slot
1630 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=NULL;fontnum++);
1631 Assert(fontnum<MAX_OPEN_FONTS); //did we find one?
1633 strncpy(open_font[fontnum].filename,fontname,FILENAME_LEN);
1635 fontfile = cfopen(fontname, "rb");
1638 con_printf(CON_VERBOSE, "Can't open font file %s", fontname);
1642 cfread(file_id, 4, 1, fontfile);
1643 if ( !strncmp( file_id, "NFSP", 4 ) ) {
1644 con_printf(CON_NORMAL, "File %s is not a font file", fontname );
1648 datasize = cfile_read_int(fontfile);
1649 datasize -= GRS_FONT_SIZE; // subtract the size of the header.
1651 MALLOC(font, grs_font, sizeof(grs_font));
1652 grs_font_read(font, fontfile);
1654 MALLOC(font_data, char, datasize);
1655 cfread(font_data, 1, datasize, fontfile);
1657 open_font[fontnum].ptr = font;
1658 open_font[fontnum].dataptr = font_data;
1660 // make these offsets relative to font_data
1661 font->ft_data = (ubyte *)((int)font->ft_data - GRS_FONT_SIZE);
1662 font->ft_widths = (short *)((int)font->ft_widths - GRS_FONT_SIZE);
1663 font->ft_kerndata = (ubyte *)((int)font->ft_kerndata - GRS_FONT_SIZE);
1665 nchars = font->ft_maxchar - font->ft_minchar + 1;
1667 if (font->ft_flags & FT_PROPORTIONAL) {
1669 font->ft_widths = (short *) &font_data[(int)font->ft_widths];
1670 font->ft_data = &font_data[(int)font->ft_data];
1671 font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1673 ptr = font->ft_data;
1675 for (i=0; i< nchars; i++ ) {
1676 font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]);
1677 font->ft_chars[i] = ptr;
1678 if (font->ft_flags & FT_COLOR)
1679 ptr += font->ft_widths[i] * font->ft_h;
1681 ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1686 font->ft_data = font_data;
1687 font->ft_chars = NULL;
1688 font->ft_widths = NULL;
1690 ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1693 if (font->ft_flags & FT_KERNED)
1694 font->ft_kerndata = &font_data[(int)font->ft_kerndata];
1696 if (font->ft_flags & FT_COLOR) { //remap palette
1697 ubyte palette[256*3];
1698 ubyte colormap[256];
1701 cfread(palette,3,256,fontfile); //read the palette
1703 #ifdef MACINTOSH // swap the first and last palette entries (black and white)
1708 for (i = 0; i < 3; i++) {
1710 palette[i] = palette[765+i];
1714 // we also need to swap the data entries as well. black is white and white is black
1716 for (i = 0; i < ptr-newfont->ft_data; i++) {
1717 if (newfont->ft_data[i] == 0)
1718 newfont->ft_data[i] = 255;
1719 else if (newfont->ft_data[i] == 255)
1720 newfont->ft_data[i] = 0;
1726 build_colormap_good( (ubyte *)&palette, colormap, freq );
1728 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // chaged from colormap[255] = 255 to this for macintosh
1730 decode_data_asm(font->ft_data, ptr - font->ft_data, colormap, freq );
1736 // memcpy(newfont,font,(ubyte*)&newfont->oldfont-(ubyte*)newfont);//fill in newfont data from oldfont struct
1737 // mprintf((0,"%i %i %i\n",sizeof(grs_font),sizeof(old_grs_font),(ubyte*)&newfont->oldfont-(ubyte*)newfont));
1747 char tests[]="abcdefghij1234.A";
1748 gr_get_string_size(tests,&x,&y,&aw);
1749 // newfont->ft_aw=x/(float)strlen(tests);
1753 ogl_init_font(font);
1760 //remap a font by re-reading its data & palette
1761 void gr_remap_font( grs_font *font, char * fontname, char *font_data )
1767 int datasize; //size up to (but not including) palette
1770 if (! (font->ft_flags & FT_COLOR))
1773 fontfile = cfopen(fontname, "rb");
1776 Error( "Can't open font file %s", fontname );
1778 cfread(file_id, 4, 1, fontfile);
1779 if ( !strncmp( file_id, "NFSP", 4 ) )
1780 Error( "File %s is not a font file", fontname );
1782 datasize = cfile_read_int(fontfile);
1783 datasize -= GRS_FONT_SIZE; // subtract the size of the header.
1785 d_free(font->ft_chars);
1786 grs_font_read(font, fontfile); // have to reread in case mission hogfile overrides font.
1788 cfread(font_data, 1, datasize, fontfile); //read raw data
1790 // make these offsets relative to font_data
1791 font->ft_data = (ubyte *)((int)font->ft_data - GRS_FONT_SIZE);
1792 font->ft_widths = (short *)((int)font->ft_widths - GRS_FONT_SIZE);
1793 font->ft_kerndata = (ubyte *)((int)font->ft_kerndata - GRS_FONT_SIZE);
1795 nchars = font->ft_maxchar - font->ft_minchar + 1;
1797 if (font->ft_flags & FT_PROPORTIONAL) {
1799 font->ft_widths = (short *) &font_data[(int)font->ft_widths];
1800 font->ft_data = &font_data[(int)font->ft_data];
1801 font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1803 ptr = font->ft_data;
1805 for (i=0; i< nchars; i++ ) {
1806 font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]);
1807 font->ft_chars[i] = ptr;
1808 if (font->ft_flags & FT_COLOR)
1809 ptr += font->ft_widths[i] * font->ft_h;
1811 ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1816 font->ft_data = font_data;
1817 font->ft_chars = NULL;
1818 font->ft_widths = NULL;
1820 ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1823 if (font->ft_flags & FT_KERNED)
1824 font->ft_kerndata = &font_data[(int)font->ft_kerndata];
1826 if (font->ft_flags & FT_COLOR) { //remap palette
1827 ubyte palette[256*3];
1828 ubyte colormap[256];
1831 cfread(palette,3,256,fontfile); //read the palette
1833 #ifdef MACINTOSH // swap the first and last palette entries (black and white)
1838 for (i = 0; i < 3; i++) {
1840 palette[i] = palette[765+i];
1844 // we also need to swap the data entries as well. black is white and white is black
1846 for (i = 0; i < ptr-newfont->ft_data; i++) {
1847 if (newfont->ft_data[i] == 0)
1848 newfont->ft_data[i] = 255;
1849 else if (newfont->ft_data[i] == 255)
1850 newfont->ft_data[i] = 0;
1856 build_colormap_good( (ubyte *)&palette, colormap, freq );
1858 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // chaged from colormap[255] = 255 to this for macintosh
1860 decode_data_asm(font->ft_data, ptr - font->ft_data, colormap, freq );
1867 if (font->ft_bitmaps)
1868 d_free( font->ft_bitmaps );
1869 gr_free_bitmap_data(&font->ft_parent_bitmap);
1870 // ogl_freebmtexture(&font->ft_parent_bitmap);
1872 ogl_init_font(font);
1877 void gr_set_fontcolor( int fg, int bg )
1883 void gr_set_curfont( grs_font * new )
1889 int gr_internal_string_clipped(int x, int y, char *s )
1892 char * text_ptr, * next_row, * text_ptr1;
1893 int r, BitMask, i, bits, width, spacing, letter, underline;
1900 while (next_row != NULL )
1902 text_ptr1 = next_row;
1906 if (x==0x8000) //centered
1907 x = get_centered_x(text_ptr1);
1911 for (r=0; r<FHEIGHT; r++) {
1912 text_ptr = text_ptr1;
1916 if (*text_ptr == '\n' ) {
1917 next_row = &text_ptr[1];
1921 if (*text_ptr == CC_COLOR) {
1922 FG_COLOR = *(text_ptr+1);
1927 if (*text_ptr == CC_LSPACING) {
1928 Int3(); // Warning: skip lines not supported for clipped strings.
1934 if (*text_ptr == CC_UNDERLINE ) {
1935 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1940 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1942 letter = *text_ptr-FMINCHAR;
1944 if (!INFONT(letter)) { //not in font, draw as space
1950 if (FFLAGS & FT_PROPORTIONAL)
1951 fp = FCHARS[letter];
1953 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1956 for (i=0; i< width; i++ ) {
1957 gr_setcolor(FG_COLOR);
1961 fp += BITS_TO_BYTES(width)*r;
1965 for (i=0; i< width; i++ ) {
1971 gr_setcolor(FG_COLOR);
1973 gr_setcolor(BG_COLOR);
1979 x += spacing-width; //for kerning
1989 int gr_internal_string_clipped_m(int x, int y, char *s )
1992 char * text_ptr, * next_row, * text_ptr1;
1993 int r, BitMask, i, bits, width, spacing, letter, underline;
2000 while (next_row != NULL )
2002 text_ptr1 = next_row;
2006 if (x==0x8000) //centered
2007 x = get_centered_x(text_ptr1);
2011 for (r=0; r<FHEIGHT; r++) {
2014 text_ptr = text_ptr1;
2017 if (*text_ptr == '\n' ) {
2018 next_row = &text_ptr[1];
2022 if (*text_ptr == CC_COLOR) {
2023 FG_COLOR = *(text_ptr+1);
2028 if (*text_ptr == CC_LSPACING) {
2029 Int3(); // Warning: skip lines not supported for clipped strings.
2035 if (*text_ptr == CC_UNDERLINE ) {
2036 if ((r==FBASELINE+2) || (r==FBASELINE+3))
2041 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
2043 letter = *text_ptr-FMINCHAR;
2045 if (!INFONT(letter)) { //not in font, draw as space
2051 if (FFLAGS & FT_PROPORTIONAL)
2052 fp = FCHARS[letter];
2054 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
2057 for (i=0; i< width; i++ ) {
2058 gr_setcolor(FG_COLOR);
2062 fp += BITS_TO_BYTES(width)*r;
2066 for (i=0; i< width; i++ ) {
2071 if (bits & BitMask) {
2072 gr_setcolor(FG_COLOR);
2081 x += spacing-width; //for kerning