1 /* $Id: font.c,v 1.23 2002-09-07 07:17:18 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.
17 * Graphical routines for drawing fonts.
33 #include "pa_enabl.h" //$$POLY_ACC
51 #define MAX_OPEN_FONTS 50
52 #define FILENAME_LEN 13
54 typedef struct openfont {
55 char filename[FILENAME_LEN];
60 //list of open fonts, for use (for now) for palette remapping
61 openfont open_font[MAX_OPEN_FONTS];
63 #define FONT grd_curcanv->cv_font
64 #define FG_COLOR grd_curcanv->cv_font_fg_color
65 #define BG_COLOR grd_curcanv->cv_font_bg_color
66 #define FWIDTH FONT->ft_w
67 #define FHEIGHT FONT->ft_h
68 #define FBASELINE FONT->ft_baseline
69 #define FFLAGS FONT->ft_flags
70 #define FMINCHAR FONT->ft_minchar
71 #define FMAXCHAR FONT->ft_maxchar
72 #define FDATA FONT->ft_data
73 #define FCHARS FONT->ft_chars
74 #define FWIDTHS FONT->ft_widths
76 #define BITS_TO_BYTES(x) (((x)+7)>>3)
78 int gr_internal_string_clipped(int x, int y, char *s );
79 int gr_internal_string_clipped_m(int x, int y, char *s );
81 ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second)
83 ubyte *p=font->ft_kerndata;
86 if (p[0]==first && p[1]==second)
94 //takes the character AFTER being offset into font
95 #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
97 //takes the character BEFORE being offset into current font
98 void get_char_width(ubyte c,ubyte c2,int *width,int *spacing)
104 if (!INFONT(letter)) { //not in font, draw as space
106 if (FFLAGS & FT_PROPORTIONAL)
113 if (FFLAGS & FT_PROPORTIONAL)
114 *width = FWIDTHS[letter];
120 if (FFLAGS & FT_KERNED) {
123 if (!(c2==0 || c2=='\n')) {
126 letter2 = c2-FMINCHAR;
128 if (INFONT(letter2)) {
130 p = find_kern_entry(FONT,(ubyte)letter,letter2);
139 int get_centered_x(char *s)
143 for (w=0;*s!=0 && *s!='\n';s++) {
147 continue;//skip color codes.
149 get_char_width(s[0],s[1],&w2,&s2);
153 return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
156 //hack to allow color codes to be embedded in strings -MPM
157 //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string.
158 //function must already have orig_color var set (or they could be passed as args...)
159 //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain
160 int gr_message_color_level=1;
161 #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x03)) { \
164 if (gr_message_color_level >= *(text_ptr-1)) \
165 FG_COLOR = *text_ptr - 1; \
169 else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \
170 if (gr_message_color_level >= *text_ptr - 3) \
171 FG_COLOR=orig_color; \
175 int gr_internal_string0(int x, int y, char *s )
178 ubyte * text_ptr, * next_row, * text_ptr1;
179 int r, BitMask, i, bits, width, spacing, letter, underline;
182 unsigned int VideoOffset, VideoOffset1;
186 VideoOffset1 = y * ROWSIZE + x;
190 while (next_row != NULL )
192 text_ptr1 = next_row;
195 if (x==0x8000) { //centered
196 int xx = get_centered_x(text_ptr1);
197 VideoOffset1 = y * ROWSIZE + xx;
200 for (r=0; r<FHEIGHT; r++)
203 text_ptr = text_ptr1;
205 VideoOffset = VideoOffset1;
209 if (*text_ptr == '\n' )
211 next_row = &text_ptr[1];
215 if (*text_ptr == CC_COLOR) {
216 FG_COLOR = *(text_ptr+1);
221 if (*text_ptr == CC_LSPACING) {
222 skip_lines = *(text_ptr+1) - '0';
228 if (*text_ptr == CC_UNDERLINE )
230 if ((r==FBASELINE+2) || (r==FBASELINE+3))
235 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
237 letter = *text_ptr-FMINCHAR;
239 if (!INFONT(letter)) { //not in font, draw as space
240 VideoOffset += spacing;
245 if (FFLAGS & FT_PROPORTIONAL)
248 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
251 for (i=0; i< width; i++ )
252 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
255 fp += BITS_TO_BYTES(width)*r;
259 for (i=0; i< width; i++ )
267 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
269 DATA[VideoOffset++] = (unsigned char) BG_COLOR;
274 VideoOffset += spacing-width; //for kerning
279 VideoOffset1 += ROWSIZE; y++;
283 VideoOffset1 += ROWSIZE * skip_lines;
289 int gr_internal_string0m(int x, int y, char *s )
292 ubyte * text_ptr, * next_row, * text_ptr1;
293 int r, BitMask, i, bits, width, spacing, letter, underline;
296 unsigned int VideoOffset, VideoOffset1;
298 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
302 VideoOffset1 = y * ROWSIZE + x;
306 while (next_row != NULL )
308 text_ptr1 = next_row;
311 if (x==0x8000) { //centered
312 int xx = get_centered_x(text_ptr1);
313 VideoOffset1 = y * ROWSIZE + xx;
316 for (r=0; r<FHEIGHT; r++)
319 text_ptr = text_ptr1;
321 VideoOffset = VideoOffset1;
325 if (*text_ptr == '\n' )
327 next_row = &text_ptr[1];
331 if (*text_ptr == CC_COLOR) {
332 FG_COLOR = *(text_ptr+1);
337 if (*text_ptr == CC_LSPACING) {
338 skip_lines = *(text_ptr+1) - '0';
344 if (*text_ptr == CC_UNDERLINE )
346 if ((r==FBASELINE+2) || (r==FBASELINE+3))
351 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
353 letter = *text_ptr-FMINCHAR;
355 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
356 CHECK_EMBEDDED_COLORS() else{
357 VideoOffset += spacing;
363 if (FFLAGS & FT_PROPORTIONAL)
366 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
369 for (i=0; i< width; i++ )
370 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
373 fp += BITS_TO_BYTES(width)*r;
377 for (i=0; i< width; i++ )
385 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
393 VideoOffset += spacing-width;
396 VideoOffset1 += ROWSIZE;
400 VideoOffset1 += ROWSIZE * skip_lines;
407 int gr_internal_string2(int x, int y, char *s )
410 ubyte * text_ptr, * next_row, * text_ptr1;
411 int r, BitMask, i, bits, width, spacing, letter, underline;
412 int page_switched, skip_lines = 0;
414 unsigned int VideoOffset, VideoOffset1;
416 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
420 gr_vesa_setpage(VideoOffset1 >> 16);
422 VideoOffset1 &= 0xFFFF;
426 while (next_row != NULL )
428 text_ptr1 = next_row;
431 if (x==0x8000) { //centered
432 int xx = get_centered_x(text_ptr1);
433 VideoOffset1 = y * ROWSIZE + xx;
434 gr_vesa_setpage(VideoOffset1 >> 16);
435 VideoOffset1 &= 0xFFFF;
438 for (r=0; r<FHEIGHT; r++)
440 text_ptr = text_ptr1;
442 VideoOffset = VideoOffset1;
448 if (*text_ptr == '\n' )
450 next_row = &text_ptr[1];
454 if (*text_ptr == CC_COLOR) {
455 FG_COLOR = *(text_ptr+1);
460 if (*text_ptr == CC_LSPACING) {
461 skip_lines = *(text_ptr+1) - '0';
467 if (*text_ptr == CC_UNDERLINE )
469 if ((r==FBASELINE+2) || (r==FBASELINE+3))
474 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
476 Assert(width==spacing); //no kerning support here
478 letter = *text_ptr-FMINCHAR;
480 if (!INFONT(letter)) { //not in font, draw as space
481 VideoOffset += spacing;
486 if (FFLAGS & FT_PROPORTIONAL)
489 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
493 if ( VideoOffset+width > 0xFFFF )
495 for (i=0; i< width; i++ )
497 gr_video_memory[VideoOffset++] = FG_COLOR;
499 if (VideoOffset > 0xFFFF )
501 VideoOffset -= 0xFFFF + 1;
509 for (i=0; i< width; i++ )
510 gr_video_memory[VideoOffset++] = FG_COLOR;
519 fp += BITS_TO_BYTES(width)*r;
523 if ( VideoOffset+width > 0xFFFF )
525 for (i=0; i< width; i++ )
533 gr_video_memory[VideoOffset++] = FG_COLOR;
535 gr_video_memory[VideoOffset++] = BG_COLOR;
539 if (VideoOffset > 0xFFFF )
541 VideoOffset -= 0xFFFF + 1;
553 if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR;
554 else gr_video_memory[VideoOffset+0] = BG_COLOR;
556 if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR;
557 else gr_video_memory[VideoOffset+1] = BG_COLOR;
559 if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR;
560 else gr_video_memory[VideoOffset+2] = BG_COLOR;
562 if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR;
563 else gr_video_memory[VideoOffset+3] = BG_COLOR;
565 if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR;
566 else gr_video_memory[VideoOffset+4] = BG_COLOR;
568 if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR;
569 else gr_video_memory[VideoOffset+5] = BG_COLOR;
571 if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR;
572 else gr_video_memory[VideoOffset+6] = BG_COLOR;
574 if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR;
575 else gr_video_memory[VideoOffset+7] = BG_COLOR;
579 for (i=0; i< width/2 ; i++ )
587 gr_video_memory[VideoOffset++] = FG_COLOR;
589 gr_video_memory[VideoOffset++] = BG_COLOR;
601 gr_video_memory[VideoOffset++] = FG_COLOR;
603 gr_video_memory[VideoOffset++] = BG_COLOR;
613 VideoOffset1 += ROWSIZE;
615 if (VideoOffset1 > 0xFFFF ) {
616 VideoOffset1 -= 0xFFFF + 1;
623 VideoOffset1 += ROWSIZE * skip_lines;
629 int gr_internal_string2m(int x, int y, char *s )
632 char * text_ptr, * next_row, * text_ptr1;
633 int r, BitMask, i, bits, width, spacing, letter, underline;
634 int page_switched, skip_lines = 0;
636 unsigned int VideoOffset, VideoOffset1;
638 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
640 gr_vesa_setpage(VideoOffset1 >> 16);
642 VideoOffset1 &= 0xFFFF;
646 while (next_row != NULL )
648 text_ptr1 = next_row;
651 if (x==0x8000) { //centered
652 int xx = get_centered_x(text_ptr1);
653 VideoOffset1 = y * ROWSIZE + xx;
654 gr_vesa_setpage(VideoOffset1 >> 16);
655 VideoOffset1 &= 0xFFFF;
658 for (r=0; r<FHEIGHT; r++)
660 text_ptr = text_ptr1;
662 VideoOffset = VideoOffset1;
668 if (*text_ptr == '\n' )
670 next_row = &text_ptr[1];
674 if (*text_ptr == CC_COLOR) {
675 FG_COLOR = *(text_ptr+1);
680 if (*text_ptr == CC_LSPACING) {
681 skip_lines = *(text_ptr+1) - '0';
687 if (*text_ptr == CC_UNDERLINE )
689 if ((r==FBASELINE+2) || (r==FBASELINE+3))
694 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
696 letter = *text_ptr-FMINCHAR;
698 if (!INFONT(letter)) { //not in font, draw as space
699 VideoOffset += width;
704 if (FFLAGS & FT_PROPORTIONAL)
707 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
711 if ( VideoOffset+width > 0xFFFF )
713 for (i=0; i< width; i++ )
715 gr_video_memory[VideoOffset++] = FG_COLOR;
717 if (VideoOffset > 0xFFFF )
719 VideoOffset -= 0xFFFF + 1;
727 for (i=0; i< width; i++ )
728 gr_video_memory[VideoOffset++] = FG_COLOR;
733 fp += BITS_TO_BYTES(width)*r;
737 if ( VideoOffset+width > 0xFFFF )
739 for (i=0; i< width; i++ )
747 gr_video_memory[VideoOffset++] = FG_COLOR;
753 if (VideoOffset > 0xFFFF )
755 VideoOffset -= 0xFFFF + 1;
762 for (i=0; i< width; i++ )
770 gr_video_memory[VideoOffset++] = FG_COLOR;
779 VideoOffset += spacing-width;
783 VideoOffset1 += ROWSIZE;
785 if (VideoOffset1 > 0xFFFF ) {
786 VideoOffset1 -= 0xFFFF + 1;
793 VideoOffset1 += ROWSIZE * skip_lines;
801 #if defined(POLY_ACC)
802 int gr_internal_string5(int x, int y, char *s )
805 ubyte * text_ptr, * next_row, * text_ptr1;
806 int r, BitMask, i, bits, width, spacing, letter, underline;
809 unsigned int VideoOffset, VideoOffset1;
812 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
816 while (next_row != NULL )
818 text_ptr1 = next_row;
821 if (x==0x8000) { //centered
822 int xx = get_centered_x(text_ptr1);
823 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
826 for (r=0; r<FHEIGHT; r++)
829 text_ptr = text_ptr1;
831 VideoOffset = VideoOffset1;
835 if (*text_ptr == '\n' )
837 next_row = &text_ptr[1];
841 if (*text_ptr == CC_COLOR) {
842 FG_COLOR = *(text_ptr+1);
847 if (*text_ptr == CC_LSPACING) {
848 skip_lines = *(text_ptr+1) - '0';
854 if (*text_ptr == CC_UNDERLINE )
856 if ((r==FBASELINE+2) || (r==FBASELINE+3))
861 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
863 letter = *text_ptr-FMINCHAR;
865 if (!INFONT(letter)) { //not in font, draw as space
866 VideoOffset += spacing * PA_BPP;
871 if (FFLAGS & FT_PROPORTIONAL)
874 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
877 for (i=0; i< width; i++ )
878 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
881 fp += BITS_TO_BYTES(width)*r;
885 for (i=0; i< width; i++ )
893 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
895 { *(short *)(DATA + VideoOffset) = pa_clut[BG_COLOR]; VideoOffset += PA_BPP; }
900 VideoOffset += PA_BPP * (spacing-width); //for kerning
905 VideoOffset1 += ROWSIZE; y++;
909 VideoOffset1 += ROWSIZE * skip_lines;
915 int gr_internal_string5m(int x, int y, char *s )
918 ubyte * text_ptr, * next_row, * text_ptr1;
919 int r, BitMask, i, bits, width, spacing, letter, underline;
922 unsigned int VideoOffset, VideoOffset1;
925 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
929 while (next_row != NULL )
931 text_ptr1 = next_row;
934 if (x==0x8000) { //centered
935 int xx = get_centered_x(text_ptr1);
936 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
939 for (r=0; r<FHEIGHT; r++)
942 text_ptr = text_ptr1;
944 VideoOffset = VideoOffset1;
948 if (*text_ptr == '\n' )
950 next_row = &text_ptr[1];
954 if (*text_ptr == CC_COLOR) {
955 FG_COLOR = *(text_ptr+1);
960 if (*text_ptr == CC_LSPACING) {
961 skip_lines = *(text_ptr+1) - '0';
967 if (*text_ptr == CC_UNDERLINE )
969 if ((r==FBASELINE+2) || (r==FBASELINE+3))
974 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
976 letter = *text_ptr-FMINCHAR;
978 if (!INFONT(letter)) { //not in font, draw as space
979 VideoOffset += spacing * PA_BPP;
984 if (FFLAGS & FT_PROPORTIONAL)
987 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
990 for (i=0; i< width; i++ )
991 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
994 fp += BITS_TO_BYTES(width)*r;
998 for (i=0; i< width; i++ )
1006 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
1008 VideoOffset += PA_BPP;
1014 VideoOffset += PA_BPP * (spacing-width);
1017 VideoOffset1 += ROWSIZE; y++;
1020 VideoOffset1 += ROWSIZE * skip_lines;
1028 //a bitmap for the character
1029 grs_bitmap char_bm = {
1032 BM_FLAG_TRANSPARENT, //flags
1035 #ifdef BITMAP_SELECTOR
1042 int gr_internal_color_string(int x, int y, char *s )
1045 ubyte * text_ptr, * next_row, * text_ptr1;
1046 int width, spacing,letter;
1049 char_bm.bm_h = FHEIGHT; //set height for chars of this font
1056 while (next_row != NULL)
1058 text_ptr1 = next_row;
1061 text_ptr = text_ptr1;
1065 if (xx==0x8000) //centered
1066 xx = get_centered_x(text_ptr);
1070 if (*text_ptr == '\n' )
1072 next_row = &text_ptr[1];
1077 letter = *text_ptr-FMINCHAR;
1079 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1081 if (!INFONT(letter)) { //not in font, draw as space
1087 if (FFLAGS & FT_PROPORTIONAL)
1088 fp = FCHARS[letter];
1090 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1092 gr_init_bitmap (&char_bm, BM_LINEAR, 0, 0, width, FHEIGHT, width, fp);
1093 gr_bitmapm(xx,yy,&char_bm);
1105 #include "../main/inferno.h"
1106 #include "ogl_init.h"
1108 //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
1110 int pow2ize(int x);//from ogl.c
1112 int get_font_total_width(grs_font * font){
1113 if (font->ft_flags & FT_PROPORTIONAL){
1114 int i,w=0,c=font->ft_minchar;
1115 for (i=0;c<=font->ft_maxchar;i++,c++){
1116 if (font->ft_widths[i]<0)
1118 w+=font->ft_widths[i];
1122 return font->ft_w*(font->ft_maxchar-font->ft_minchar+1);
1125 void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){
1126 int nchars = font->ft_maxchar-font->ft_minchar+1;
1127 int r,x,y,nc=0,smallest=999999,smallr=-1,tries;
1128 int smallprop=10000;
1130 for (h=32;h<=256;h*=2){
1131 // h=pow2ize(font->ft_h*rows+gap*(rows-1));
1132 if (font->ft_h>h)continue;
1133 r=(h/(font->ft_h+gap));
1134 w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r);
1140 mprintf((0,"failed to fit (%ix%i, %ic)\n",w,h,nc));
1145 while(y+font->ft_h<=h){
1150 if (font->ft_flags & FT_PROPORTIONAL){
1151 if (x+font->ft_widths[nc]+gap>w)break;
1152 x+=font->ft_widths[nc++]+gap;
1154 if (x+font->ft_w+gap>w)break;
1168 mprintf((0,"fit: %ix%i %i tries\n",w,h,tries));
1170 if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32)
1191 Error("couldn't fit font?\n");
1192 mprintf((0,"using %ix%i\n",*rw,*rh));
1196 void ogl_init_font(grs_font * font){
1197 int nchars = font->ft_maxchar-font->ft_minchar+1;
1198 int i,w,h,tw,th,x,y,curx=0,cury=0;
1200 // char data[32*32*4];
1202 int gap=0;//having a gap just wastes ram, since we don't filter text textures at all.
1204 ogl_font_choose_size(font,gap,&tw,&th);
1205 data=d_malloc(tw*th);
1206 gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data);
1208 font->ft_parent_bitmap.gltexture=ogl_get_free_texture();
1210 font->ft_bitmaps=(grs_bitmap*)d_malloc( nchars * sizeof(grs_bitmap));
1211 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));
1216 for(i=0;i<nchars;i++){
1217 // s[0]=font->ft_minchar+i;
1218 // gr_get_string_size(s,&w,&h,&aw);
1219 if (font->ft_flags & FT_PROPORTIONAL)
1220 w=font->ft_widths[i];
1223 // mprintf((0,"char %i(%ix%i): ",i,w,h));
1225 mprintf((0,"grr\n"));continue;
1232 Error("font doesn't really fit (%i/%i)?\n",i,nchars);
1233 if (font->ft_flags & FT_COLOR) {
1234 if (font->ft_flags & FT_PROPORTIONAL)
1235 fp = font->ft_chars[i];
1237 fp = font->ft_data + i * w*h;
1240 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w];
1243 // gr_init_bitmap(&font->ft_bitmaps[i],BM_LINEAR,0,0,w,h,w,font->);
1245 int BitMask,bits=0,white=gr_find_closest_color(63,63,63);
1246 // if (w*h>sizeof(data))
1247 // Error("ogl_init_font: toobig\n");
1248 if (font->ft_flags & FT_PROPORTIONAL)
1249 fp = font->ft_chars[i];
1251 fp = font->ft_data + i * BITS_TO_BYTES(w)*h;
1254 for (x=0; x< w; x++ )
1262 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white;
1264 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255;
1269 gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h);
1273 if (!(font->ft_flags & FT_COLOR)) {
1274 //use GL_INTENSITY instead of GL_RGB
1275 if (ogl_intensity4_ok){
1276 font->ft_parent_bitmap.gltexture->internalformat=GL_INTENSITY4;
1277 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE;
1278 }else if (ogl_luminance4_alpha4_ok){
1279 font->ft_parent_bitmap.gltexture->internalformat=GL_LUMINANCE4_ALPHA4;
1280 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE_ALPHA;
1281 }else if (ogl_rgba2_ok){
1282 font->ft_parent_bitmap.gltexture->internalformat=GL_RGBA2;
1283 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1285 font->ft_parent_bitmap.gltexture->internalformat=ogl_rgba_format;
1286 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1289 ogl_loadbmtexture_m(&font->ft_parent_bitmap,0);
1292 int ogl_internal_string(int x, int y, char *s )
1294 ubyte * text_ptr, * next_row, * text_ptr1;
1295 int width, spacing,letter;
1297 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
1303 if (grd_curscreen->sc_canvas.cv_bitmap.bm_type != BM_OGL)
1305 while (next_row != NULL)
1307 text_ptr1 = next_row;
1310 text_ptr = text_ptr1;
1314 if (xx==0x8000) //centered
1315 xx = get_centered_x(text_ptr);
1319 if (*text_ptr == '\n' )
1321 next_row = &text_ptr[1];
1326 letter = *text_ptr-FMINCHAR;
1328 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1330 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
1331 CHECK_EMBEDDED_COLORS() else{
1338 // ogl_ubitblt(FONT->ft_bitmaps[letter].bm_w,FONT->ft_bitmaps[letter].bm_h,xx,yy,0,0,&FONT->ft_bitmaps[letter],NULL);
1339 // if (*text_ptr>='0' && *text_ptr<='9'){
1340 if (FFLAGS&FT_COLOR)
1341 gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);
1343 if (grd_curcanv->cv_bitmap.bm_type==BM_OGL)
1344 ogl_ubitmapm_c(xx,yy,&FONT->ft_bitmaps[letter],FG_COLOR);
1346 Error("ogl_internal_string: non-color string to non-ogl dest\n");
1347 // gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);//ignores color..
1360 int gr_internal_color_string(int x, int y, char *s ){
1361 return ogl_internal_string(x,y,s);
1365 int gr_string(int x, int y, char *s )
1370 Assert(FONT != NULL);
1372 if ( x == 0x8000 ) {
1373 if ( y<0 ) clipped |= 1;
1374 gr_get_string_size(s, &w, &h, &aw );
1375 // for x, since this will be centered, only look at
1377 if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1378 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1380 if ( (y+h) < 0 ) clipped |= 2;
1381 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1384 if ( (x<0) || (y<0) ) clipped |= 1;
1385 gr_get_string_size(s, &w, &h, &aw );
1386 if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1387 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1388 if ( (x+w) < 0 ) clipped |= 2;
1389 if ( (y+h) < 0 ) clipped |= 2;
1390 if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;
1391 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1395 return gr_ustring(x, y, s );
1397 if ( clipped & 2 ) {
1398 // Completely clipped...
1399 mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
1403 if ( clipped & 1 ) {
1404 // Partially clipped...
1405 //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
1408 // Partially clipped...
1411 return ogl_internal_string(x,y,s);
1414 if (FFLAGS & FT_COLOR)
1415 return gr_internal_color_string( x, y, s);
1417 if ( BG_COLOR == -1)
1418 return gr_internal_string_clipped_m( x, y, s );
1420 return gr_internal_string_clipped( x, y, s );
1423 int gr_ustring(int x, int y, char *s )
1427 return ogl_internal_string(x,y,s);
1430 if (FFLAGS & FT_COLOR) {
1432 return gr_internal_color_string(x,y,s);
1439 if ( BG_COLOR == -1)
1440 return gr_internal_string0m(x,y,s);
1442 return gr_internal_string0(x,y,s);
1445 if ( BG_COLOR == -1)
1446 return gr_internal_string2m(x,y,s);
1448 return gr_internal_string2(x,y,s);
1450 #if defined(POLY_ACC)
1452 if ( BG_COLOR == -1)
1453 return gr_internal_string5m(x,y,s);
1455 return gr_internal_string5(x,y,s);
1462 void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width )
1464 int i = 0, longest_width = 0;
1467 *string_height = FHEIGHT;
1469 *average_width = FWIDTH;
1476 // if (*s == CC_UNDERLINE)
1481 *string_height += FHEIGHT;
1487 // 1 = next byte specifies color, so skip the 1 and the color value
1490 else if (*s == CC_LSPACING) {
1491 *string_height += *(s+1)-'0';
1494 get_char_width(s[0],s[1],&width,&spacing);
1496 *string_width += spacing;
1498 if (*string_width > longest_width)
1499 longest_width = *string_width;
1506 *string_width = longest_width;
1510 int gr_uprintf( int x, int y, char * format, ... )
1515 va_start(args, format );
1516 vsprintf(buffer,format,args);
1517 return gr_ustring( x, y, buffer );
1520 int gr_printf( int x, int y, char * format, ... )
1525 va_start(args, format );
1526 vsprintf(buffer,format,args);
1527 return gr_string( x, y, buffer );
1530 void gr_close_font( grs_font * font )
1538 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=font;fontnum++);
1539 Assert(fontnum<MAX_OPEN_FONTS); //did we find slot?
1541 font_data = open_font[fontnum].dataptr;
1542 d_free( font_data );
1544 open_font[fontnum].ptr = NULL;
1545 open_font[fontnum].dataptr = NULL;
1547 if ( font->ft_chars )
1548 d_free( font->ft_chars );
1550 if (font->ft_bitmaps)
1551 d_free( font->ft_bitmaps );
1552 gr_free_bitmap_data(&font->ft_parent_bitmap);
1553 // ogl_freebmtexture(&font->ft_parent_bitmap);
1561 //remap (by re-reading) all the color fonts
1562 void gr_remap_color_fonts()
1566 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1569 font = open_font[fontnum].ptr;
1571 if (font && (font->ft_flags & FT_COLOR))
1572 gr_remap_font(font, open_font[fontnum].filename, open_font[fontnum].dataptr);
1577 #define grs_font_read(gf, fp) cfread(gf, GRS_FONT_SIZE, 1, fp)
1580 * reads a grs_font structure from a CFILE
1582 void grs_font_read(grs_font *gf, CFILE *fp)
1584 gf->ft_w = cfile_read_short(fp);
1585 gf->ft_h = cfile_read_short(fp);
1586 gf->ft_flags = cfile_read_short(fp);
1587 gf->ft_baseline = cfile_read_short(fp);
1588 gf->ft_minchar = cfile_read_byte(fp);
1589 gf->ft_maxchar = cfile_read_byte(fp);
1590 gf->ft_bytewidth = cfile_read_short(fp);
1591 gf->ft_data = (ubyte *)cfile_read_int(fp);
1592 gf->ft_chars = (ubyte **)cfile_read_int(fp);
1593 gf->ft_widths = (short *)cfile_read_int(fp);
1594 gf->ft_kerndata = (ubyte *)cfile_read_int(fp);
1598 grs_font * gr_init_font( char * fontname )
1600 static int first_time=1;
1604 unsigned char * ptr;
1608 int datasize; //size up to (but not including) palette
1612 for (i=0;i<MAX_OPEN_FONTS;i++)
1613 open_font[i].ptr = NULL;
1614 open_font[i].dataptr = NULL;
1618 //find free font slot
1619 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=NULL;fontnum++);
1620 Assert(fontnum<MAX_OPEN_FONTS); //did we find one?
1622 strncpy(open_font[fontnum].filename,fontname,FILENAME_LEN);
1624 fontfile = cfopen(fontname, "rb");
1627 con_printf(CON_VERBOSE, "Can't open font file %s\n", fontname);
1631 cfread(file_id, 4, 1, fontfile);
1632 if ( !strncmp( file_id, "NFSP", 4 ) ) {
1633 con_printf(CON_NORMAL, "File %s is not a font file\n", fontname );
1637 datasize = cfile_read_int(fontfile);
1638 datasize -= GRS_FONT_SIZE; // subtract the size of the header.
1640 MALLOC(font, grs_font, sizeof(grs_font));
1641 grs_font_read(font, fontfile);
1643 MALLOC(font_data, char, datasize);
1644 cfread(font_data, 1, datasize, fontfile);
1646 open_font[fontnum].ptr = font;
1647 open_font[fontnum].dataptr = font_data;
1649 // make these offsets relative to font_data
1650 font->ft_data = (ubyte *)((int)font->ft_data - GRS_FONT_SIZE);
1651 font->ft_widths = (short *)((int)font->ft_widths - GRS_FONT_SIZE);
1652 font->ft_kerndata = (ubyte *)((int)font->ft_kerndata - GRS_FONT_SIZE);
1654 nchars = font->ft_maxchar - font->ft_minchar + 1;
1656 if (font->ft_flags & FT_PROPORTIONAL) {
1658 font->ft_widths = (short *) &font_data[(int)font->ft_widths];
1659 font->ft_data = &font_data[(int)font->ft_data];
1660 font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1662 ptr = font->ft_data;
1664 for (i=0; i< nchars; i++ ) {
1665 font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]);
1666 font->ft_chars[i] = ptr;
1667 if (font->ft_flags & FT_COLOR)
1668 ptr += font->ft_widths[i] * font->ft_h;
1670 ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1675 font->ft_data = font_data;
1676 font->ft_chars = NULL;
1677 font->ft_widths = NULL;
1679 ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1682 if (font->ft_flags & FT_KERNED)
1683 font->ft_kerndata = &font_data[(int)font->ft_kerndata];
1685 if (font->ft_flags & FT_COLOR) { //remap palette
1686 ubyte palette[256*3];
1687 ubyte colormap[256];
1690 cfread(palette,3,256,fontfile); //read the palette
1692 #ifdef SWAP_0_255 // swap the first and last palette entries (black and white)
1697 for (i = 0; i < 3; i++) {
1699 palette[i] = palette[765+i];
1703 // we also need to swap the data entries as well. black is white and white is black
1705 for (i = 0; i < ptr-font->ft_data; i++) {
1706 if (font->ft_data[i] == 0)
1707 font->ft_data[i] = 255;
1708 else if (font->ft_data[i] == 255)
1709 font->ft_data[i] = 0;
1715 build_colormap_good( (ubyte *)&palette, colormap, freq );
1717 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255 to this for macintosh
1719 decode_data_asm(font->ft_data, ptr - font->ft_data, colormap, freq );
1733 char tests[]="abcdefghij1234.A";
1734 gr_get_string_size(tests,&x,&y,&aw);
1735 // newfont->ft_aw=x/(float)strlen(tests);
1739 ogl_init_font(font);
1746 //remap a font by re-reading its data & palette
1747 void gr_remap_font( grs_font *font, char * fontname, char *font_data )
1753 int datasize; //size up to (but not including) palette
1756 if (! (font->ft_flags & FT_COLOR))
1759 fontfile = cfopen(fontname, "rb");
1762 Error( "Can't open font file %s", fontname );
1764 cfread(file_id, 4, 1, fontfile);
1765 if ( !strncmp( file_id, "NFSP", 4 ) )
1766 Error( "File %s is not a font file", fontname );
1768 datasize = cfile_read_int(fontfile);
1769 datasize -= GRS_FONT_SIZE; // subtract the size of the header.
1771 d_free(font->ft_chars);
1772 grs_font_read(font, fontfile); // have to reread in case mission hogfile overrides font.
1774 cfread(font_data, 1, datasize, fontfile); //read raw data
1776 // make these offsets relative to font_data
1777 font->ft_data = (ubyte *)((int)font->ft_data - GRS_FONT_SIZE);
1778 font->ft_widths = (short *)((int)font->ft_widths - GRS_FONT_SIZE);
1779 font->ft_kerndata = (ubyte *)((int)font->ft_kerndata - GRS_FONT_SIZE);
1781 nchars = font->ft_maxchar - font->ft_minchar + 1;
1783 if (font->ft_flags & FT_PROPORTIONAL) {
1785 font->ft_widths = (short *) &font_data[(int)font->ft_widths];
1786 font->ft_data = &font_data[(int)font->ft_data];
1787 font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1789 ptr = font->ft_data;
1791 for (i=0; i< nchars; i++ ) {
1792 font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]);
1793 font->ft_chars[i] = ptr;
1794 if (font->ft_flags & FT_COLOR)
1795 ptr += font->ft_widths[i] * font->ft_h;
1797 ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1802 font->ft_data = font_data;
1803 font->ft_chars = NULL;
1804 font->ft_widths = NULL;
1806 ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1809 if (font->ft_flags & FT_KERNED)
1810 font->ft_kerndata = &font_data[(int)font->ft_kerndata];
1812 if (font->ft_flags & FT_COLOR) { //remap palette
1813 ubyte palette[256*3];
1814 ubyte colormap[256];
1817 cfread(palette,3,256,fontfile); //read the palette
1819 #ifdef SWAP_0_255 // swap the first and last palette entries (black and white)
1824 for (i = 0; i < 3; i++) {
1826 palette[i] = palette[765+i];
1830 // we also need to swap the data entries as well. black is white and white is black
1832 for (i = 0; i < ptr-font->ft_data; i++) {
1833 if (font->ft_data[i] == 0)
1834 font->ft_data[i] = 255;
1835 else if (font->ft_data[i] == 255)
1836 font->ft_data[i] = 0;
1842 build_colormap_good( (ubyte *)&palette, colormap, freq );
1844 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255 to this for macintosh
1846 decode_data_asm(font->ft_data, ptr - font->ft_data, colormap, freq );
1853 if (font->ft_bitmaps)
1854 d_free( font->ft_bitmaps );
1855 gr_free_bitmap_data(&font->ft_parent_bitmap);
1856 // ogl_freebmtexture(&font->ft_parent_bitmap);
1858 ogl_init_font(font);
1863 void gr_set_fontcolor( int fg, int bg )
1869 void gr_set_curfont( grs_font * new )
1875 int gr_internal_string_clipped(int x, int y, char *s )
1878 char * text_ptr, * next_row, * text_ptr1;
1879 int r, BitMask, i, bits, width, spacing, letter, underline;
1886 while (next_row != NULL )
1888 text_ptr1 = next_row;
1892 if (x==0x8000) //centered
1893 x = get_centered_x(text_ptr1);
1897 for (r=0; r<FHEIGHT; r++) {
1898 text_ptr = text_ptr1;
1902 if (*text_ptr == '\n' ) {
1903 next_row = &text_ptr[1];
1907 if (*text_ptr == CC_COLOR) {
1908 FG_COLOR = *(text_ptr+1);
1913 if (*text_ptr == CC_LSPACING) {
1914 Int3(); // Warning: skip lines not supported for clipped strings.
1920 if (*text_ptr == CC_UNDERLINE ) {
1921 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1926 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1928 letter = *text_ptr-FMINCHAR;
1930 if (!INFONT(letter)) { //not in font, draw as space
1936 if (FFLAGS & FT_PROPORTIONAL)
1937 fp = FCHARS[letter];
1939 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1942 for (i=0; i< width; i++ ) {
1943 gr_setcolor(FG_COLOR);
1947 fp += BITS_TO_BYTES(width)*r;
1951 for (i=0; i< width; i++ ) {
1957 gr_setcolor(FG_COLOR);
1959 gr_setcolor(BG_COLOR);
1965 x += spacing-width; //for kerning
1975 int gr_internal_string_clipped_m(int x, int y, char *s )
1978 char * text_ptr, * next_row, * text_ptr1;
1979 int r, BitMask, i, bits, width, spacing, letter, underline;
1986 while (next_row != NULL )
1988 text_ptr1 = next_row;
1992 if (x==0x8000) //centered
1993 x = get_centered_x(text_ptr1);
1997 for (r=0; r<FHEIGHT; r++) {
2000 text_ptr = text_ptr1;
2003 if (*text_ptr == '\n' ) {
2004 next_row = &text_ptr[1];
2008 if (*text_ptr == CC_COLOR) {
2009 FG_COLOR = *(text_ptr+1);
2014 if (*text_ptr == CC_LSPACING) {
2015 Int3(); // Warning: skip lines not supported for clipped strings.
2021 if (*text_ptr == CC_UNDERLINE ) {
2022 if ((r==FBASELINE+2) || (r==FBASELINE+3))
2027 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
2029 letter = *text_ptr-FMINCHAR;
2031 if (!INFONT(letter)) { //not in font, draw as space
2037 if (FFLAGS & FT_PROPORTIONAL)
2038 fp = FCHARS[letter];
2040 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
2043 for (i=0; i< width; i++ ) {
2044 gr_setcolor(FG_COLOR);
2048 fp += BITS_TO_BYTES(width)*r;
2052 for (i=0; i< width; i++ ) {
2057 if (bits & BitMask) {
2058 gr_setcolor(FG_COLOR);
2067 x += spacing-width; //for kerning