1 /* $Id: font.c,v 1.38 2005-07-30 01:51:42 chris 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.
30 #if !defined(_MSC_VER) && !defined(macintosh)
48 #define MAX_OPEN_FONTS 50
49 #define FILENAME_LEN 13
51 typedef struct openfont {
52 char filename[FILENAME_LEN];
57 //list of open fonts, for use (for now) for palette remapping
58 openfont open_font[MAX_OPEN_FONTS];
60 #define FONT grd_curcanv->cv_font
61 #define FG_COLOR grd_curcanv->cv_font_fg_color
62 #define BG_COLOR grd_curcanv->cv_font_bg_color
63 #define FWIDTH FONT->ft_w
64 #define FHEIGHT FONT->ft_h
65 #define FBASELINE FONT->ft_baseline
66 #define FFLAGS FONT->ft_flags
67 #define FMINCHAR FONT->ft_minchar
68 #define FMAXCHAR FONT->ft_maxchar
69 #define FDATA FONT->ft_data
70 #define FCHARS FONT->ft_chars
71 #define FWIDTHS FONT->ft_widths
73 #define BITS_TO_BYTES(x) (((x)+7)>>3)
75 int gr_internal_string_clipped(int x, int y, char *s );
76 int gr_internal_string_clipped_m(int x, int y, char *s );
78 ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second)
80 ubyte *p=font->ft_kerndata;
83 if (p[0]==first && p[1]==second)
91 //takes the character AFTER being offset into font
92 #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
94 //takes the character BEFORE being offset into current font
95 void get_char_width(ubyte c,ubyte c2,int *width,int *spacing)
101 if (!INFONT(letter)) { //not in font, draw as space
103 if (FFLAGS & FT_PROPORTIONAL)
110 if (FFLAGS & FT_PROPORTIONAL)
111 *width = FWIDTHS[letter];
117 if (FFLAGS & FT_KERNED) {
120 if (!(c2==0 || c2=='\n')) {
123 letter2 = c2-FMINCHAR;
125 if (INFONT(letter2)) {
127 p = find_kern_entry(FONT,(ubyte)letter,letter2);
136 int get_centered_x(char *s)
140 for (w=0;*s!=0 && *s!='\n';s++) {
144 continue;//skip color codes.
146 get_char_width(s[0],s[1],&w2,&s2);
150 return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
153 //hack to allow color codes to be embedded in strings -MPM
154 //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string.
155 //function must already have orig_color var set (or they could be passed as args...)
156 //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain
157 int gr_message_color_level=1;
158 #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x03)) { \
161 if (gr_message_color_level >= *(text_ptr-1)) \
162 FG_COLOR = *text_ptr - 1; \
166 else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \
167 if (gr_message_color_level >= *text_ptr - 3) \
168 FG_COLOR=orig_color; \
172 int gr_internal_string0(int x, int y, char *s )
175 char * text_ptr, * next_row, * text_ptr1;
176 int r, BitMask, i, bits, width, spacing, letter, underline;
179 unsigned int VideoOffset, VideoOffset1;
183 VideoOffset1 = y * ROWSIZE + x;
187 while (next_row != NULL )
189 text_ptr1 = next_row;
192 if (x==0x8000) { //centered
193 int xx = get_centered_x(text_ptr1);
194 VideoOffset1 = y * ROWSIZE + xx;
197 for (r=0; r<FHEIGHT; r++)
200 text_ptr = text_ptr1;
202 VideoOffset = VideoOffset1;
206 if (*text_ptr == '\n' )
208 next_row = &text_ptr[1];
212 if (*text_ptr == CC_COLOR) {
213 FG_COLOR = *(text_ptr+1);
218 if (*text_ptr == CC_LSPACING) {
219 skip_lines = *(text_ptr+1) - '0';
225 if (*text_ptr == CC_UNDERLINE )
227 if ((r==FBASELINE+2) || (r==FBASELINE+3))
232 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
234 letter = (unsigned char)*text_ptr - FMINCHAR;
236 if (!INFONT(letter)) { //not in font, draw as space
237 VideoOffset += spacing;
242 if (FFLAGS & FT_PROPORTIONAL)
245 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
248 for (i=0; i< width; i++ )
249 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
252 fp += BITS_TO_BYTES(width)*r;
256 for (i=0; i< width; i++ )
264 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
266 DATA[VideoOffset++] = (unsigned char) BG_COLOR;
271 VideoOffset += spacing-width; //for kerning
276 VideoOffset1 += ROWSIZE; y++;
280 VideoOffset1 += ROWSIZE * skip_lines;
286 int gr_internal_string0m(int x, int y, char *s )
289 char * text_ptr, * next_row, * text_ptr1;
290 int r, BitMask, i, bits, width, spacing, letter, underline;
293 unsigned int VideoOffset, VideoOffset1;
295 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
299 VideoOffset1 = y * ROWSIZE + x;
303 while (next_row != NULL )
305 text_ptr1 = next_row;
308 if (x==0x8000) { //centered
309 int xx = get_centered_x(text_ptr1);
310 VideoOffset1 = y * ROWSIZE + xx;
313 for (r=0; r<FHEIGHT; r++)
316 text_ptr = text_ptr1;
318 VideoOffset = VideoOffset1;
322 if (*text_ptr == '\n' )
324 next_row = &text_ptr[1];
328 if (*text_ptr == CC_COLOR) {
329 FG_COLOR = *(text_ptr+1);
334 if (*text_ptr == CC_LSPACING) {
335 skip_lines = *(text_ptr+1) - '0';
341 if (*text_ptr == CC_UNDERLINE )
343 if ((r==FBASELINE+2) || (r==FBASELINE+3))
348 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
350 letter = (unsigned char)*text_ptr-FMINCHAR;
352 if (!INFONT(letter) || (unsigned char) *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 unsigned 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;
800 //a bitmap for the character
801 grs_bitmap char_bm = {
804 BM_FLAG_TRANSPARENT, //flags
807 #ifdef BITMAP_SELECTOR
814 int gr_internal_color_string(int x, int y, char *s )
817 char *text_ptr, *next_row, *text_ptr1;
818 int width, spacing,letter;
821 char_bm.bm_h = FHEIGHT; //set height for chars of this font
828 while (next_row != NULL)
830 text_ptr1 = next_row;
833 text_ptr = text_ptr1;
837 if (xx==0x8000) //centered
838 xx = get_centered_x(text_ptr);
842 if (*text_ptr == '\n' )
844 next_row = &text_ptr[1];
849 letter = (unsigned char)*text_ptr - FMINCHAR;
851 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
853 if (!INFONT(letter)) { //not in font, draw as space
859 if (FFLAGS & FT_PROPORTIONAL)
862 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
864 gr_init_bitmap (&char_bm, BM_LINEAR, 0, 0, width, FHEIGHT, width, fp);
865 gr_bitmapm(xx,yy,&char_bm);
878 #include "ogl_init.h"
880 //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
882 int pow2ize(int x);//from ogl.c
884 int get_font_total_width(grs_font * font){
885 if (font->ft_flags & FT_PROPORTIONAL){
886 int i,w=0,c=font->ft_minchar;
887 for (i=0;c<=font->ft_maxchar;i++,c++){
888 if (font->ft_widths[i]<0)
890 w+=font->ft_widths[i];
894 return font->ft_w*(font->ft_maxchar-font->ft_minchar+1);
897 void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){
898 int nchars = font->ft_maxchar-font->ft_minchar+1;
899 int r,x,y,nc=0,smallest=999999,smallr=-1,tries;
902 for (h=32;h<=256;h*=2){
903 // h=pow2ize(font->ft_h*rows+gap*(rows-1));
904 if (font->ft_h>h)continue;
905 r=(h/(font->ft_h+gap));
906 w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r);
912 mprintf((0,"failed to fit (%ix%i, %ic)\n",w,h,nc));
917 while(y+font->ft_h<=h){
922 if (font->ft_flags & FT_PROPORTIONAL){
923 if (x+font->ft_widths[nc]+gap>w)break;
924 x+=font->ft_widths[nc++]+gap;
926 if (x+font->ft_w+gap>w)break;
940 mprintf((0,"fit: %ix%i %i tries\n",w,h,tries));
942 if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32)
963 Error("couldn't fit font?\n");
964 mprintf((0,"using %ix%i\n",*rw,*rh));
968 void ogl_init_font(grs_font * font){
969 int oglflags = OGL_FLAG_ALPHA;
970 int nchars = font->ft_maxchar-font->ft_minchar+1;
971 int i,w,h,tw,th,x,y,curx=0,cury=0;
973 // char data[32*32*4];
975 int gap=0;//having a gap just wastes ram, since we don't filter text textures at all.
977 ogl_font_choose_size(font,gap,&tw,&th);
978 data=d_malloc(tw*th);
979 memset(data, 0, tw * th);
980 gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data);
981 gr_set_transparent(&font->ft_parent_bitmap, 1);
983 if (!(font->ft_flags & FT_COLOR))
984 oglflags |= OGL_FLAG_NOCOLOR;
985 ogl_init_texture(font->ft_parent_bitmap.gltexture = ogl_get_free_texture(), tw, th, oglflags); // have to init the gltexture here so the subbitmaps will find it.
987 font->ft_bitmaps=(grs_bitmap*)d_malloc( nchars * sizeof(grs_bitmap));
988 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));
993 for(i=0;i<nchars;i++){
994 // s[0]=font->ft_minchar+i;
995 // gr_get_string_size(s,&w,&h,&aw);
996 if (font->ft_flags & FT_PROPORTIONAL)
997 w=font->ft_widths[i];
1000 // mprintf((0,"char %i(%ix%i): ",i,w,h));
1002 mprintf((0,"grr\n"));continue;
1009 Error("font doesn't really fit (%i/%i)?\n",i,nchars);
1010 if (font->ft_flags & FT_COLOR) {
1011 if (font->ft_flags & FT_PROPORTIONAL)
1012 fp = font->ft_chars[i];
1014 fp = font->ft_data + i * w*h;
1017 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w];
1020 // gr_init_bitmap(&font->ft_bitmaps[i],BM_LINEAR,0,0,w,h,w,font->);
1022 int BitMask,bits=0,white=gr_find_closest_color(63,63,63);
1023 // if (w*h>sizeof(data))
1024 // Error("ogl_init_font: toobig\n");
1025 if (font->ft_flags & FT_PROPORTIONAL)
1026 fp = font->ft_chars[i];
1028 fp = font->ft_data + i * BITS_TO_BYTES(w)*h;
1031 for (x=0; x< w; x++ )
1039 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white;
1041 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255;
1046 gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h);
1050 ogl_loadbmtexture_f(&font->ft_parent_bitmap, oglflags);
1053 int ogl_internal_string(int x, int y, char *s )
1055 char * text_ptr, * next_row, * text_ptr1;
1056 int width, spacing,letter;
1058 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
1064 if (grd_curscreen->sc_canvas.cv_bitmap.bm_type != BM_OGL)
1066 while (next_row != NULL)
1068 text_ptr1 = next_row;
1071 text_ptr = text_ptr1;
1075 if (xx==0x8000) //centered
1076 xx = get_centered_x(text_ptr);
1080 if (*text_ptr == '\n' )
1082 next_row = &text_ptr[1];
1087 letter = (unsigned char)*text_ptr - FMINCHAR;
1089 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1091 if (!INFONT(letter) || (unsigned char)*text_ptr <= 0x06)
1092 { //not in font, draw as space
1093 CHECK_EMBEDDED_COLORS() else{
1100 // ogl_ubitblt(FONT->ft_bitmaps[letter].bm_w,FONT->ft_bitmaps[letter].bm_h,xx,yy,0,0,&FONT->ft_bitmaps[letter],NULL);
1101 // if (*text_ptr>='0' && *text_ptr<='9'){
1102 if (FFLAGS&FT_COLOR)
1103 gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);
1105 if (grd_curcanv->cv_bitmap.bm_type==BM_OGL)
1106 ogl_ubitmapm_c(xx,yy,&FONT->ft_bitmaps[letter],FG_COLOR);
1108 Error("ogl_internal_string: non-color string to non-ogl dest\n");
1109 // gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);//ignores color..
1122 int gr_internal_color_string(int x, int y, char *s ){
1123 return ogl_internal_string(x,y,s);
1127 int gr_string(int x, int y, char *s )
1132 Assert(FONT != NULL);
1134 if ( x == 0x8000 ) {
1135 if ( y<0 ) clipped |= 1;
1136 gr_get_string_size(s, &w, &h, &aw );
1137 // for x, since this will be centered, only look at
1139 if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1140 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1142 if ( (y+h) < 0 ) clipped |= 2;
1143 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1146 if ( (x<0) || (y<0) ) clipped |= 1;
1147 gr_get_string_size(s, &w, &h, &aw );
1148 if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1149 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1150 if ( (x+w) < 0 ) clipped |= 2;
1151 if ( (y+h) < 0 ) clipped |= 2;
1152 if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;
1153 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1157 return gr_ustring(x, y, s );
1159 if ( clipped & 2 ) {
1160 // Completely clipped...
1161 mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
1165 if ( clipped & 1 ) {
1166 // Partially clipped...
1167 //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
1170 // Partially clipped...
1173 return ogl_internal_string(x,y,s);
1176 if (FFLAGS & FT_COLOR)
1177 return gr_internal_color_string( x, y, s);
1179 if ( BG_COLOR == -1)
1180 return gr_internal_string_clipped_m( x, y, s );
1182 return gr_internal_string_clipped( x, y, s );
1185 int gr_ustring(int x, int y, char *s )
1189 return ogl_internal_string(x,y,s);
1192 if (FFLAGS & FT_COLOR) {
1194 return gr_internal_color_string(x,y,s);
1201 if ( BG_COLOR == -1)
1202 return gr_internal_string0m(x,y,s);
1204 return gr_internal_string0(x,y,s);
1207 if ( BG_COLOR == -1)
1208 return gr_internal_string2m(x,y,s);
1210 return gr_internal_string2(x,y,s);
1217 void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width )
1219 int i = 0, longest_width = 0;
1222 *string_height = FHEIGHT;
1224 *average_width = FWIDTH;
1231 // if (*s == CC_UNDERLINE)
1236 *string_height += FHEIGHT;
1242 // 1 = next byte specifies color, so skip the 1 and the color value
1245 else if (*s == CC_LSPACING) {
1246 *string_height += *(s+1)-'0';
1249 get_char_width(s[0],s[1],&width,&spacing);
1251 *string_width += spacing;
1253 if (*string_width > longest_width)
1254 longest_width = *string_width;
1261 *string_width = longest_width;
1265 int gr_uprintf( int x, int y, char * format, ... )
1270 va_start(args, format );
1271 vsprintf(buffer,format,args);
1272 return gr_ustring( x, y, buffer );
1275 int gr_printf( int x, int y, char * format, ... )
1280 va_start(args, format );
1281 vsprintf(buffer,format,args);
1282 return gr_string( x, y, buffer );
1285 void gr_close_font( grs_font * font )
1293 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=font;fontnum++);
1294 Assert(fontnum<MAX_OPEN_FONTS); //did we find slot?
1296 font_data = open_font[fontnum].dataptr;
1297 d_free( font_data );
1299 open_font[fontnum].ptr = NULL;
1300 open_font[fontnum].dataptr = NULL;
1302 if ( font->ft_chars )
1303 d_free( font->ft_chars );
1305 if (font->ft_bitmaps)
1306 d_free( font->ft_bitmaps );
1307 gr_free_bitmap_data(&font->ft_parent_bitmap);
1308 // ogl_freebmtexture(&font->ft_parent_bitmap);
1316 //remap (by re-reading) all the color fonts
1317 void gr_remap_color_fonts()
1321 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1324 font = open_font[fontnum].ptr;
1326 if (font && (font->ft_flags & FT_COLOR))
1327 gr_remap_font(font, open_font[fontnum].filename, open_font[fontnum].dataptr);
1331 void gr_remap_mono_fonts()
1334 con_printf (CON_DEBUG, "gr_remap_mono_fonts ()\n");
1335 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1337 font = open_font[fontnum].ptr;
1338 if (font && !(font->ft_flags & FT_COLOR))
1339 gr_remap_font(font, open_font[fontnum].filename, open_font[fontnum].dataptr);
1344 #define grs_font_read(gf, fp) cfread(gf, GRS_FONT_SIZE, 1, fp)
1347 * reads a grs_font structure from a CFILE
1349 void grs_font_read(grs_font *gf, CFILE *fp)
1351 gf->ft_w = cfile_read_short(fp);
1352 gf->ft_h = cfile_read_short(fp);
1353 gf->ft_flags = cfile_read_short(fp);
1354 gf->ft_baseline = cfile_read_short(fp);
1355 gf->ft_minchar = cfile_read_byte(fp);
1356 gf->ft_maxchar = cfile_read_byte(fp);
1357 gf->ft_bytewidth = cfile_read_short(fp);
1358 gf->ft_data = (ubyte *)cfile_read_int(fp);
1359 gf->ft_chars = (ubyte **)cfile_read_int(fp);
1360 gf->ft_widths = (short *)cfile_read_int(fp);
1361 gf->ft_kerndata = (ubyte *)cfile_read_int(fp);
1365 grs_font * gr_init_font( char * fontname )
1367 static int first_time=1;
1371 unsigned char * ptr;
1375 int datasize; //size up to (but not including) palette
1379 for (i=0;i<MAX_OPEN_FONTS;i++)
1381 open_font[i].ptr = NULL;
1382 open_font[i].dataptr = NULL;
1387 //find free font slot
1388 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=NULL;fontnum++);
1389 Assert(fontnum<MAX_OPEN_FONTS); //did we find one?
1391 strncpy(open_font[fontnum].filename,fontname,FILENAME_LEN);
1393 fontfile = cfopen(fontname, "rb");
1396 con_printf(CON_VERBOSE, "Can't open font file %s\n", fontname);
1400 cfread(file_id, 4, 1, fontfile);
1401 if ( !strncmp( file_id, "NFSP", 4 ) ) {
1402 con_printf(CON_NORMAL, "File %s is not a font file\n", fontname );
1406 datasize = cfile_read_int(fontfile);
1407 datasize -= GRS_FONT_SIZE; // subtract the size of the header.
1409 MALLOC(font, grs_font, sizeof(grs_font));
1410 grs_font_read(font, fontfile);
1412 MALLOC(font_data, char, datasize);
1413 cfread(font_data, 1, datasize, fontfile);
1415 open_font[fontnum].ptr = font;
1416 open_font[fontnum].dataptr = font_data;
1418 // make these offsets relative to font_data
1419 font->ft_data = (ubyte *)((int)font->ft_data - GRS_FONT_SIZE);
1420 font->ft_widths = (short *)((int)font->ft_widths - GRS_FONT_SIZE);
1421 font->ft_kerndata = (ubyte *)((int)font->ft_kerndata - GRS_FONT_SIZE);
1423 nchars = font->ft_maxchar - font->ft_minchar + 1;
1425 if (font->ft_flags & FT_PROPORTIONAL) {
1427 font->ft_widths = (short *) &font_data[(int)font->ft_widths];
1428 font->ft_data = (unsigned char *) &font_data[(int)font->ft_data];
1429 font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1431 ptr = font->ft_data;
1433 for (i=0; i< nchars; i++ ) {
1434 font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]);
1435 font->ft_chars[i] = ptr;
1436 if (font->ft_flags & FT_COLOR)
1437 ptr += font->ft_widths[i] * font->ft_h;
1439 ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1444 font->ft_data = (unsigned char *) font_data;
1445 font->ft_chars = NULL;
1446 font->ft_widths = NULL;
1448 ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1451 if (font->ft_flags & FT_KERNED)
1452 font->ft_kerndata = (unsigned char *) &font_data[(int)font->ft_kerndata];
1454 if (font->ft_flags & FT_COLOR) { //remap palette
1455 ubyte palette[256*3];
1456 ubyte colormap[256];
1459 cfread(palette,3,256,fontfile); //read the palette
1461 #ifdef SWAP_0_255 // swap the first and last palette entries (black and white)
1466 for (i = 0; i < 3; i++) {
1468 palette[i] = palette[765+i];
1472 // we also need to swap the data entries as well. black is white and white is black
1474 for (i = 0; i < ptr-font->ft_data; i++) {
1475 if (font->ft_data[i] == 0)
1476 font->ft_data[i] = 255;
1477 else if (font->ft_data[i] == 255)
1478 font->ft_data[i] = 0;
1484 build_colormap_good( (ubyte *)&palette, colormap, freq );
1486 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255 to this for macintosh
1488 decode_data_asm(font->ft_data, ptr - font->ft_data, colormap, freq );
1502 char tests[]="abcdefghij1234.A";
1503 gr_get_string_size(tests,&x,&y,&aw);
1504 // newfont->ft_aw=x/(float)strlen(tests);
1508 ogl_init_font(font);
1515 //remap a font by re-reading its data & palette
1516 void gr_remap_font( grs_font *font, char * fontname, char *font_data )
1522 int datasize; //size up to (but not including) palette
1525 if (! (font->ft_flags & FT_COLOR))
1528 fontfile = cfopen(fontname, "rb");
1531 Error( "Can't open font file %s", fontname );
1533 cfread(file_id, 4, 1, fontfile);
1534 if ( !strncmp( file_id, "NFSP", 4 ) )
1535 Error( "File %s is not a font file", fontname );
1537 datasize = cfile_read_int(fontfile);
1538 datasize -= GRS_FONT_SIZE; // subtract the size of the header.
1540 d_free(font->ft_chars);
1541 grs_font_read(font, fontfile); // have to reread in case mission hogfile overrides font.
1543 cfread(font_data, 1, datasize, fontfile); //read raw data
1545 // make these offsets relative to font_data
1546 font->ft_data = (ubyte *)((int)font->ft_data - GRS_FONT_SIZE);
1547 font->ft_widths = (short *)((int)font->ft_widths - GRS_FONT_SIZE);
1548 font->ft_kerndata = (ubyte *)((int)font->ft_kerndata - GRS_FONT_SIZE);
1550 nchars = font->ft_maxchar - font->ft_minchar + 1;
1552 if (font->ft_flags & FT_PROPORTIONAL) {
1554 font->ft_widths = (short *) &font_data[(int)font->ft_widths];
1555 font->ft_data = (unsigned char *) &font_data[(int)font->ft_data];
1556 font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1558 ptr = font->ft_data;
1560 for (i=0; i< nchars; i++ ) {
1561 font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]);
1562 font->ft_chars[i] = ptr;
1563 if (font->ft_flags & FT_COLOR)
1564 ptr += font->ft_widths[i] * font->ft_h;
1566 ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1571 font->ft_data = (unsigned char *) font_data;
1572 font->ft_chars = NULL;
1573 font->ft_widths = NULL;
1575 ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1578 if (font->ft_flags & FT_KERNED)
1579 font->ft_kerndata = (unsigned char *) &font_data[(int)font->ft_kerndata];
1581 if (font->ft_flags & FT_COLOR) { //remap palette
1582 ubyte palette[256*3];
1583 ubyte colormap[256];
1586 cfread(palette,3,256,fontfile); //read the palette
1588 #ifdef SWAP_0_255 // swap the first and last palette entries (black and white)
1593 for (i = 0; i < 3; i++) {
1595 palette[i] = palette[765+i];
1599 // we also need to swap the data entries as well. black is white and white is black
1601 for (i = 0; i < ptr-font->ft_data; i++) {
1602 if (font->ft_data[i] == 0)
1603 font->ft_data[i] = 255;
1604 else if (font->ft_data[i] == 255)
1605 font->ft_data[i] = 0;
1611 build_colormap_good( (ubyte *)&palette, colormap, freq );
1613 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255 to this for macintosh
1615 decode_data_asm(font->ft_data, ptr - font->ft_data, colormap, freq );
1622 if (font->ft_bitmaps)
1623 d_free( font->ft_bitmaps );
1624 gr_free_bitmap_data(&font->ft_parent_bitmap);
1625 // ogl_freebmtexture(&font->ft_parent_bitmap);
1627 ogl_init_font(font);
1632 void gr_set_fontcolor( int fg, int bg )
1638 void gr_set_curfont( grs_font * new )
1644 int gr_internal_string_clipped(int x, int y, char *s )
1647 char * text_ptr, * next_row, * text_ptr1;
1648 int r, BitMask, i, bits, width, spacing, letter, underline;
1655 while (next_row != NULL )
1657 text_ptr1 = next_row;
1661 if (x==0x8000) //centered
1662 x = get_centered_x(text_ptr1);
1666 for (r=0; r<FHEIGHT; r++) {
1667 text_ptr = text_ptr1;
1671 if (*text_ptr == '\n' ) {
1672 next_row = &text_ptr[1];
1676 if (*text_ptr == CC_COLOR) {
1677 FG_COLOR = *(text_ptr+1);
1682 if (*text_ptr == CC_LSPACING) {
1683 Int3(); // Warning: skip lines not supported for clipped strings.
1689 if (*text_ptr == CC_UNDERLINE ) {
1690 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1695 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1697 letter = *text_ptr-FMINCHAR;
1699 if (!INFONT(letter)) { //not in font, draw as space
1705 if (FFLAGS & FT_PROPORTIONAL)
1706 fp = FCHARS[letter];
1708 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1711 for (i=0; i< width; i++ ) {
1712 gr_setcolor(FG_COLOR);
1716 fp += BITS_TO_BYTES(width)*r;
1720 for (i=0; i< width; i++ ) {
1726 gr_setcolor(FG_COLOR);
1728 gr_setcolor(BG_COLOR);
1734 x += spacing-width; //for kerning
1744 int gr_internal_string_clipped_m(int x, int y, char *s )
1747 char * text_ptr, * next_row, * text_ptr1;
1748 int r, BitMask, i, bits, width, spacing, letter, underline;
1755 while (next_row != NULL )
1757 text_ptr1 = next_row;
1761 if (x==0x8000) //centered
1762 x = get_centered_x(text_ptr1);
1766 for (r=0; r<FHEIGHT; r++) {
1769 text_ptr = text_ptr1;
1772 if (*text_ptr == '\n' ) {
1773 next_row = &text_ptr[1];
1777 if (*text_ptr == CC_COLOR) {
1778 FG_COLOR = *(text_ptr+1);
1783 if (*text_ptr == CC_LSPACING) {
1784 Int3(); // Warning: skip lines not supported for clipped strings.
1790 if (*text_ptr == CC_UNDERLINE ) {
1791 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1796 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1798 letter = *text_ptr-FMINCHAR;
1800 if (!INFONT(letter)) { //not in font, draw as space
1806 if (FFLAGS & FT_PROPORTIONAL)
1807 fp = FCHARS[letter];
1809 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1812 for (i=0; i< width; i++ ) {
1813 gr_setcolor(FG_COLOR);
1817 fp += BITS_TO_BYTES(width)*r;
1821 for (i=0; i< width; i++ ) {
1826 if (bits & BitMask) {
1827 gr_setcolor(FG_COLOR);
1836 x += spacing-width; //for kerning