2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
16 * Graphical routines for drawing fonts.
29 #if !defined(_MSC_VER) && !defined(macintosh)
47 #define MAX_OPEN_FONTS 50
48 #define FILENAME_LEN 13
50 typedef struct openfont {
51 char filename[FILENAME_LEN];
56 //list of open fonts, for use (for now) for palette remapping
57 openfont open_font[MAX_OPEN_FONTS];
59 #define FONT grd_curcanv->cv_font
60 #define FG_COLOR grd_curcanv->cv_font_fg_color
61 #define BG_COLOR grd_curcanv->cv_font_bg_color
62 #define FWIDTH FONT->ft_w
63 #define FHEIGHT FONT->ft_h
64 #define FBASELINE FONT->ft_baseline
65 #define FFLAGS FONT->ft_flags
66 #define FMINCHAR FONT->ft_minchar
67 #define FMAXCHAR FONT->ft_maxchar
68 #define FDATA FONT->ft_data
69 #define FCHARS FONT->ft_chars
70 #define FWIDTHS FONT->ft_widths
72 #define BITS_TO_BYTES(x) (((x)+7)>>3)
74 int gr_internal_string_clipped(int x, int y, char *s );
75 int gr_internal_string_clipped_m(int x, int y, char *s );
77 ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second)
79 ubyte *p=font->ft_kerndata;
82 if (p[0]==first && p[1]==second)
90 //takes the character AFTER being offset into font
91 #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
93 //takes the character BEFORE being offset into current font
94 void get_char_width(ubyte c,ubyte c2,int *width,int *spacing)
100 if (!INFONT(letter)) { //not in font, draw as space
102 if (FFLAGS & FT_PROPORTIONAL)
109 if (FFLAGS & FT_PROPORTIONAL)
110 *width = FWIDTHS[letter];
116 if (FFLAGS & FT_KERNED) {
119 if (!(c2==0 || c2=='\n')) {
122 letter2 = c2-FMINCHAR;
124 if (INFONT(letter2)) {
126 p = find_kern_entry(FONT,(ubyte)letter,letter2);
135 int get_centered_x(char *s)
139 for (w=0;*s!=0 && *s!='\n';s++) {
143 continue;//skip color codes.
145 get_char_width(s[0],s[1],&w2,&s2);
149 return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
152 //hack to allow color codes to be embedded in strings -MPM
153 //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string.
154 //function must already have orig_color var set (or they could be passed as args...)
155 //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain
156 int gr_message_color_level=1;
157 #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x03)) { \
160 if (gr_message_color_level >= *(text_ptr-1)) \
161 FG_COLOR = *text_ptr - 1; \
165 else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \
166 if (gr_message_color_level >= *text_ptr - 3) \
167 FG_COLOR=orig_color; \
171 int gr_internal_string0(int x, int y, char *s )
174 char * text_ptr, * next_row, * text_ptr1;
175 int r, BitMask, i, bits, width, spacing, letter, underline;
178 unsigned int VideoOffset, VideoOffset1;
182 VideoOffset1 = y * ROWSIZE + x;
186 while (next_row != NULL )
188 text_ptr1 = next_row;
191 if (x==0x8000) { //centered
192 int xx = get_centered_x(text_ptr1);
193 VideoOffset1 = y * ROWSIZE + xx;
196 for (r=0; r<FHEIGHT; r++)
199 text_ptr = text_ptr1;
201 VideoOffset = VideoOffset1;
205 if (*text_ptr == '\n' )
207 next_row = &text_ptr[1];
211 if (*text_ptr == CC_COLOR) {
212 FG_COLOR = *(text_ptr+1);
217 if (*text_ptr == CC_LSPACING) {
218 skip_lines = *(text_ptr+1) - '0';
224 if (*text_ptr == CC_UNDERLINE )
226 if ((r==FBASELINE+2) || (r==FBASELINE+3))
231 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
233 letter = (unsigned char)*text_ptr - FMINCHAR;
235 if (!INFONT(letter)) { //not in font, draw as space
236 VideoOffset += spacing;
241 if (FFLAGS & FT_PROPORTIONAL)
244 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
247 for (i=0; i< width; i++ )
248 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
251 fp += BITS_TO_BYTES(width)*r;
255 for (i=0; i< width; i++ )
263 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
265 DATA[VideoOffset++] = (unsigned char) BG_COLOR;
270 VideoOffset += spacing-width; //for kerning
275 VideoOffset1 += ROWSIZE; y++;
279 VideoOffset1 += ROWSIZE * skip_lines;
285 int gr_internal_string0m(int x, int y, char *s )
288 char * text_ptr, * next_row, * text_ptr1;
289 int r, BitMask, i, bits, width, spacing, letter, underline;
292 unsigned int VideoOffset, VideoOffset1;
294 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
298 VideoOffset1 = y * ROWSIZE + x;
302 while (next_row != NULL )
304 text_ptr1 = next_row;
307 if (x==0x8000) { //centered
308 int xx = get_centered_x(text_ptr1);
309 VideoOffset1 = y * ROWSIZE + xx;
312 for (r=0; r<FHEIGHT; r++)
315 text_ptr = text_ptr1;
317 VideoOffset = VideoOffset1;
321 if (*text_ptr == '\n' )
323 next_row = &text_ptr[1];
327 if (*text_ptr == CC_COLOR) {
328 FG_COLOR = *(text_ptr+1);
333 if (*text_ptr == CC_LSPACING) {
334 skip_lines = *(text_ptr+1) - '0';
340 if (*text_ptr == CC_UNDERLINE )
342 if ((r==FBASELINE+2) || (r==FBASELINE+3))
347 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
349 letter = (unsigned char)*text_ptr-FMINCHAR;
351 if (!INFONT(letter) || (unsigned char) *text_ptr <= 0x06) //not in font, draw as space
353 CHECK_EMBEDDED_COLORS() else{
354 VideoOffset += spacing;
360 if (FFLAGS & FT_PROPORTIONAL)
363 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
366 for (i=0; i< width; i++ )
367 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
370 fp += BITS_TO_BYTES(width)*r;
374 for (i=0; i< width; i++ )
382 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
390 VideoOffset += spacing-width;
393 VideoOffset1 += ROWSIZE;
397 VideoOffset1 += ROWSIZE * skip_lines;
404 int gr_internal_string2(int x, int y, char *s )
407 ubyte * text_ptr, * next_row, * text_ptr1;
408 int r, BitMask, i, bits, width, spacing, letter, underline;
409 int page_switched, skip_lines = 0;
411 unsigned int VideoOffset, VideoOffset1;
413 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
417 gr_vesa_setpage(VideoOffset1 >> 16);
419 VideoOffset1 &= 0xFFFF;
423 while (next_row != NULL )
425 text_ptr1 = next_row;
428 if (x==0x8000) { //centered
429 int xx = get_centered_x(text_ptr1);
430 VideoOffset1 = y * ROWSIZE + xx;
431 gr_vesa_setpage(VideoOffset1 >> 16);
432 VideoOffset1 &= 0xFFFF;
435 for (r=0; r<FHEIGHT; r++)
437 text_ptr = text_ptr1;
439 VideoOffset = VideoOffset1;
445 if (*text_ptr == '\n' )
447 next_row = &text_ptr[1];
451 if (*text_ptr == CC_COLOR) {
452 FG_COLOR = *(text_ptr+1);
457 if (*text_ptr == CC_LSPACING) {
458 skip_lines = *(text_ptr+1) - '0';
464 if (*text_ptr == CC_UNDERLINE )
466 if ((r==FBASELINE+2) || (r==FBASELINE+3))
471 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
473 Assert(width==spacing); //no kerning support here
475 letter = *text_ptr-FMINCHAR;
477 if (!INFONT(letter)) { //not in font, draw as space
478 VideoOffset += spacing;
483 if (FFLAGS & FT_PROPORTIONAL)
486 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
490 if ( VideoOffset+width > 0xFFFF )
492 for (i=0; i< width; i++ )
494 gr_video_memory[VideoOffset++] = FG_COLOR;
496 if (VideoOffset > 0xFFFF )
498 VideoOffset -= 0xFFFF + 1;
506 for (i=0; i< width; i++ )
507 gr_video_memory[VideoOffset++] = FG_COLOR;
516 fp += BITS_TO_BYTES(width)*r;
520 if ( VideoOffset+width > 0xFFFF )
522 for (i=0; i< width; i++ )
530 gr_video_memory[VideoOffset++] = FG_COLOR;
532 gr_video_memory[VideoOffset++] = BG_COLOR;
536 if (VideoOffset > 0xFFFF )
538 VideoOffset -= 0xFFFF + 1;
550 if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR;
551 else gr_video_memory[VideoOffset+0] = BG_COLOR;
553 if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR;
554 else gr_video_memory[VideoOffset+1] = BG_COLOR;
556 if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR;
557 else gr_video_memory[VideoOffset+2] = BG_COLOR;
559 if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR;
560 else gr_video_memory[VideoOffset+3] = BG_COLOR;
562 if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR;
563 else gr_video_memory[VideoOffset+4] = BG_COLOR;
565 if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR;
566 else gr_video_memory[VideoOffset+5] = BG_COLOR;
568 if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR;
569 else gr_video_memory[VideoOffset+6] = BG_COLOR;
571 if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR;
572 else gr_video_memory[VideoOffset+7] = BG_COLOR;
576 for (i=0; i< width/2 ; i++ )
584 gr_video_memory[VideoOffset++] = FG_COLOR;
586 gr_video_memory[VideoOffset++] = BG_COLOR;
598 gr_video_memory[VideoOffset++] = FG_COLOR;
600 gr_video_memory[VideoOffset++] = BG_COLOR;
610 VideoOffset1 += ROWSIZE;
612 if (VideoOffset1 > 0xFFFF ) {
613 VideoOffset1 -= 0xFFFF + 1;
620 VideoOffset1 += ROWSIZE * skip_lines;
626 int gr_internal_string2m(int x, int y, char *s )
629 unsigned char * text_ptr, * next_row, * text_ptr1;
630 int r, BitMask, i, bits, width, spacing, letter, underline;
631 int page_switched, skip_lines = 0;
633 unsigned int VideoOffset, VideoOffset1;
635 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
637 gr_vesa_setpage(VideoOffset1 >> 16);
639 VideoOffset1 &= 0xFFFF;
643 while (next_row != NULL )
645 text_ptr1 = next_row;
648 if (x==0x8000) { //centered
649 int xx = get_centered_x(text_ptr1);
650 VideoOffset1 = y * ROWSIZE + xx;
651 gr_vesa_setpage(VideoOffset1 >> 16);
652 VideoOffset1 &= 0xFFFF;
655 for (r=0; r<FHEIGHT; r++)
657 text_ptr = text_ptr1;
659 VideoOffset = VideoOffset1;
665 if (*text_ptr == '\n' )
667 next_row = &text_ptr[1];
671 if (*text_ptr == CC_COLOR) {
672 FG_COLOR = *(text_ptr+1);
677 if (*text_ptr == CC_LSPACING) {
678 skip_lines = *(text_ptr+1) - '0';
684 if (*text_ptr == CC_UNDERLINE )
686 if ((r==FBASELINE+2) || (r==FBASELINE+3))
691 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
693 letter = *text_ptr-FMINCHAR;
695 if (!INFONT(letter)) { //not in font, draw as space
696 VideoOffset += width;
701 if (FFLAGS & FT_PROPORTIONAL)
704 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
708 if ( VideoOffset+width > 0xFFFF )
710 for (i=0; i< width; i++ )
712 gr_video_memory[VideoOffset++] = FG_COLOR;
714 if (VideoOffset > 0xFFFF )
716 VideoOffset -= 0xFFFF + 1;
724 for (i=0; i< width; i++ )
725 gr_video_memory[VideoOffset++] = FG_COLOR;
730 fp += BITS_TO_BYTES(width)*r;
734 if ( VideoOffset+width > 0xFFFF )
736 for (i=0; i< width; i++ )
744 gr_video_memory[VideoOffset++] = FG_COLOR;
750 if (VideoOffset > 0xFFFF )
752 VideoOffset -= 0xFFFF + 1;
759 for (i=0; i< width; i++ )
767 gr_video_memory[VideoOffset++] = FG_COLOR;
776 VideoOffset += spacing-width;
780 VideoOffset1 += ROWSIZE;
782 if (VideoOffset1 > 0xFFFF ) {
783 VideoOffset1 -= 0xFFFF + 1;
790 VideoOffset1 += ROWSIZE * skip_lines;
799 //a bitmap for the character
800 grs_bitmap char_bm = {
803 BM_FLAG_TRANSPARENT, //flags
806 #ifdef BITMAP_SELECTOR
813 int gr_internal_color_string(int x, int y, char *s )
816 char *text_ptr, *next_row, *text_ptr1;
817 int width, spacing,letter;
820 char_bm.bm_h = FHEIGHT; //set height for chars of this font
827 while (next_row != NULL)
829 text_ptr1 = next_row;
832 text_ptr = text_ptr1;
836 if (xx==0x8000) //centered
837 xx = get_centered_x(text_ptr);
841 if (*text_ptr == '\n' )
843 next_row = &text_ptr[1];
848 letter = (unsigned char)*text_ptr - FMINCHAR;
850 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
852 if (!INFONT(letter)) { //not in font, draw as space
858 if (FFLAGS & FT_PROPORTIONAL)
861 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
863 gr_init_bitmap (&char_bm, BM_LINEAR, 0, 0, width, FHEIGHT, width, fp);
864 gr_bitmapm(xx,yy,&char_bm);
877 #include "ogl_init.h"
879 //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
881 int pow2ize(int x);//from ogl.c
883 int get_font_total_width(grs_font * font){
884 if (font->ft_flags & FT_PROPORTIONAL){
885 int i,w=0,c=font->ft_minchar;
886 for (i=0;c<=font->ft_maxchar;i++,c++){
887 if (font->ft_widths[i]<0)
889 w+=font->ft_widths[i];
893 return font->ft_w*(font->ft_maxchar-font->ft_minchar+1);
896 void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){
897 int nchars = font->ft_maxchar-font->ft_minchar+1;
898 int r,x,y,nc=0,smallest=999999,smallr=-1,tries;
901 for (h=32;h<=256;h*=2){
902 // h=pow2ize(font->ft_h*rows+gap*(rows-1));
903 if (font->ft_h>h)continue;
904 r=(h/(font->ft_h+gap));
905 w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r);
911 mprintf((0,"failed to fit (%ix%i, %ic)\n",w,h,nc));
916 while(y+font->ft_h<=h){
921 if (font->ft_flags & FT_PROPORTIONAL){
922 if (x+font->ft_widths[nc]+gap>w)break;
923 x+=font->ft_widths[nc++]+gap;
925 if (x+font->ft_w+gap>w)break;
939 mprintf((0,"fit: %ix%i %i tries\n",w,h,tries));
941 if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32)
962 Error("couldn't fit font?\n");
963 mprintf((0,"using %ix%i\n",*rw,*rh));
967 void ogl_init_font(grs_font * font){
968 int oglflags = OGL_FLAG_ALPHA;
969 int nchars = font->ft_maxchar-font->ft_minchar+1;
970 int i,w,h,tw,th,x,y,curx=0,cury=0;
972 // char data[32*32*4];
974 int gap=0;//having a gap just wastes ram, since we don't filter text textures at all.
976 ogl_font_choose_size(font,gap,&tw,&th);
977 data=d_malloc(tw*th);
978 memset(data, 0, tw * th);
979 gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data);
980 gr_set_transparent(&font->ft_parent_bitmap, 1);
982 if (!(font->ft_flags & FT_COLOR))
983 oglflags |= OGL_FLAG_NOCOLOR;
984 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.
986 font->ft_bitmaps=(grs_bitmap*)d_malloc( nchars * sizeof(grs_bitmap));
987 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));
992 for(i=0;i<nchars;i++){
993 // s[0]=font->ft_minchar+i;
994 // gr_get_string_size(s,&w,&h,&aw);
995 if (font->ft_flags & FT_PROPORTIONAL)
996 w=font->ft_widths[i];
999 // mprintf((0,"char %i(%ix%i): ",i,w,h));
1001 mprintf((0,"grr\n"));continue;
1008 Error("font doesn't really fit (%i/%i)?\n",i,nchars);
1009 if (font->ft_flags & FT_COLOR) {
1010 if (font->ft_flags & FT_PROPORTIONAL)
1011 fp = font->ft_chars[i];
1013 fp = font->ft_data + i * w*h;
1016 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w];
1019 // gr_init_bitmap(&font->ft_bitmaps[i],BM_LINEAR,0,0,w,h,w,font->);
1021 int BitMask,bits=0,white=gr_find_closest_color(63,63,63);
1022 // if (w*h>sizeof(data))
1023 // Error("ogl_init_font: toobig\n");
1024 if (font->ft_flags & FT_PROPORTIONAL)
1025 fp = font->ft_chars[i];
1027 fp = font->ft_data + i * BITS_TO_BYTES(w)*h;
1030 for (x=0; x< w; x++ )
1038 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white;
1040 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255;
1045 gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h);
1049 ogl_loadbmtexture_f(&font->ft_parent_bitmap, oglflags);
1052 int ogl_internal_string(int x, int y, char *s )
1054 char * text_ptr, * next_row, * text_ptr1;
1055 int width, spacing,letter;
1057 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 if (*text_ptr == CC_LSPACING) {
1088 skip_lines = *(text_ptr+1) - '0';
1093 if (*text_ptr == CC_UNDERLINE ) {
1098 letter = (unsigned char)*text_ptr - FMINCHAR;
1100 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1102 if (!INFONT(letter) || (unsigned char)*text_ptr <= 0x06)
1103 { //not in font, draw as space
1104 CHECK_EMBEDDED_COLORS() else{
1111 // ogl_ubitblt(FONT->ft_bitmaps[letter].bm_w,FONT->ft_bitmaps[letter].bm_h,xx,yy,0,0,&FONT->ft_bitmaps[letter],NULL);
1112 // if (*text_ptr>='0' && *text_ptr<='9'){
1113 if (FFLAGS&FT_COLOR)
1114 gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);
1116 if (grd_curcanv->cv_bitmap.bm_type==BM_OGL)
1117 ogl_ubitmapm_c(xx,yy,&FONT->ft_bitmaps[letter],FG_COLOR);
1119 Error("ogl_internal_string: non-color string to non-ogl dest\n");
1120 // gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);//ignores color..
1135 int gr_internal_color_string(int x, int y, char *s ){
1136 return ogl_internal_string(x,y,s);
1140 int gr_string(int x, int y, char *s )
1145 Assert(FONT != NULL);
1147 if ( x == 0x8000 ) {
1148 if ( y<0 ) clipped |= 1;
1149 gr_get_string_size(s, &w, &h, &aw );
1150 // for x, since this will be centered, only look at
1152 if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1153 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1155 if ( (y+h) < 0 ) clipped |= 2;
1156 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1159 if ( (x<0) || (y<0) ) clipped |= 1;
1160 gr_get_string_size(s, &w, &h, &aw );
1161 if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1162 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1163 if ( (x+w) < 0 ) clipped |= 2;
1164 if ( (y+h) < 0 ) clipped |= 2;
1165 if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;
1166 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1170 return gr_ustring(x, y, s );
1172 if ( clipped & 2 ) {
1173 // Completely clipped...
1174 mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
1178 if ( clipped & 1 ) {
1179 // Partially clipped...
1180 //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
1183 // Partially clipped...
1186 return ogl_internal_string(x,y,s);
1189 if (FFLAGS & FT_COLOR)
1190 return gr_internal_color_string( x, y, s);
1192 if ( BG_COLOR == -1)
1193 return gr_internal_string_clipped_m( x, y, s );
1195 return gr_internal_string_clipped( x, y, s );
1198 int gr_ustring(int x, int y, char *s )
1202 return ogl_internal_string(x,y,s);
1205 if (FFLAGS & FT_COLOR) {
1207 return gr_internal_color_string(x,y,s);
1214 if ( BG_COLOR == -1)
1215 return gr_internal_string0m(x,y,s);
1217 return gr_internal_string0(x,y,s);
1220 if ( BG_COLOR == -1)
1221 return gr_internal_string2m(x,y,s);
1223 return gr_internal_string2(x,y,s);
1230 void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width )
1232 int i = 0, longest_width = 0;
1235 *string_height = FHEIGHT;
1237 *average_width = FWIDTH;
1244 // if (*s == CC_UNDERLINE)
1249 *string_height += FHEIGHT;
1255 // 1 = next byte specifies color, so skip the 1 and the color value
1258 else if (*s == CC_LSPACING) {
1259 *string_height += *(s+1)-'0';
1262 get_char_width(s[0],s[1],&width,&spacing);
1264 *string_width += spacing;
1266 if (*string_width > longest_width)
1267 longest_width = *string_width;
1274 *string_width = longest_width;
1278 int gr_uprintf( int x, int y, char * format, ... )
1283 va_start(args, format );
1284 vsprintf(buffer,format,args);
1285 return gr_ustring( x, y, buffer );
1288 int gr_printf( int x, int y, char * format, ... )
1293 va_start(args, format );
1294 vsprintf(buffer,format,args);
1295 return gr_string( x, y, buffer );
1298 void gr_close_font( grs_font * font )
1306 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=font;fontnum++);
1307 Assert(fontnum<MAX_OPEN_FONTS); //did we find slot?
1309 font_data = open_font[fontnum].dataptr;
1310 d_free( font_data );
1312 open_font[fontnum].ptr = NULL;
1313 open_font[fontnum].dataptr = NULL;
1315 if ( font->ft_chars )
1316 d_free( font->ft_chars );
1318 if (font->ft_bitmaps)
1319 d_free( font->ft_bitmaps );
1320 gr_free_bitmap_data(&font->ft_parent_bitmap);
1321 // ogl_freebmtexture(&font->ft_parent_bitmap);
1329 //remap (by re-reading) all the color fonts
1330 void gr_remap_color_fonts()
1334 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1337 font = open_font[fontnum].ptr;
1339 if (font && (font->ft_flags & FT_COLOR))
1340 gr_remap_font(font, open_font[fontnum].filename, open_font[fontnum].dataptr);
1344 void gr_remap_mono_fonts()
1347 con_printf (CON_DEBUG, "gr_remap_mono_fonts ()\n");
1348 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1350 font = open_font[fontnum].ptr;
1351 if (font && !(font->ft_flags & FT_COLOR))
1352 gr_remap_font(font, open_font[fontnum].filename, open_font[fontnum].dataptr);
1357 #define grs_font_read(gf, fp) cfread(gf, GRS_FONT_SIZE, 1, fp)
1360 * reads a grs_font structure from a CFILE
1362 void grs_font_read(grs_font *gf, CFILE *fp)
1364 gf->ft_w = cfile_read_short(fp);
1365 gf->ft_h = cfile_read_short(fp);
1366 gf->ft_flags = cfile_read_short(fp);
1367 gf->ft_baseline = cfile_read_short(fp);
1368 gf->ft_minchar = cfile_read_byte(fp);
1369 gf->ft_maxchar = cfile_read_byte(fp);
1370 gf->ft_bytewidth = cfile_read_short(fp);
1371 gf->ft_data = (ubyte *)cfile_read_int(fp);
1372 gf->ft_chars = (ubyte **)cfile_read_int(fp);
1373 gf->ft_widths = (short *)cfile_read_int(fp);
1374 gf->ft_kerndata = (ubyte *)cfile_read_int(fp);
1378 grs_font * gr_init_font( char * fontname )
1380 static int first_time=1;
1384 unsigned char * ptr;
1388 int datasize; //size up to (but not including) palette
1392 for (i=0;i<MAX_OPEN_FONTS;i++)
1394 open_font[i].ptr = NULL;
1395 open_font[i].dataptr = NULL;
1400 //find free font slot
1401 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=NULL;fontnum++);
1402 Assert(fontnum<MAX_OPEN_FONTS); //did we find one?
1404 strncpy(open_font[fontnum].filename,fontname,FILENAME_LEN);
1406 fontfile = cfopen(fontname, "rb");
1409 con_printf(CON_VERBOSE, "Can't open font file %s\n", fontname);
1413 cfread(file_id, 4, 1, fontfile);
1414 if ( !strncmp( file_id, "NFSP", 4 ) ) {
1415 con_printf(CON_NORMAL, "File %s is not a font file\n", fontname );
1419 datasize = cfile_read_int(fontfile);
1420 datasize -= GRS_FONT_SIZE; // subtract the size of the header.
1422 MALLOC(font, grs_font, sizeof(grs_font));
1423 grs_font_read(font, fontfile);
1425 MALLOC(font_data, char, datasize);
1426 cfread(font_data, 1, datasize, fontfile);
1428 open_font[fontnum].ptr = font;
1429 open_font[fontnum].dataptr = font_data;
1431 // make these offsets relative to font_data
1432 font->ft_data = (ubyte *)((int)font->ft_data - GRS_FONT_SIZE);
1433 font->ft_widths = (short *)((int)font->ft_widths - GRS_FONT_SIZE);
1434 font->ft_kerndata = (ubyte *)((int)font->ft_kerndata - GRS_FONT_SIZE);
1436 nchars = font->ft_maxchar - font->ft_minchar + 1;
1438 if (font->ft_flags & FT_PROPORTIONAL) {
1440 font->ft_widths = (short *) &font_data[(int)font->ft_widths];
1441 font->ft_data = (unsigned char *) &font_data[(int)font->ft_data];
1442 font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1444 ptr = font->ft_data;
1446 for (i=0; i< nchars; i++ ) {
1447 font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]);
1448 font->ft_chars[i] = ptr;
1449 if (font->ft_flags & FT_COLOR)
1450 ptr += font->ft_widths[i] * font->ft_h;
1452 ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1457 font->ft_data = (unsigned char *) font_data;
1458 font->ft_chars = NULL;
1459 font->ft_widths = NULL;
1461 ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1464 if (font->ft_flags & FT_KERNED)
1465 font->ft_kerndata = (unsigned char *) &font_data[(int)font->ft_kerndata];
1467 if (font->ft_flags & FT_COLOR) { //remap palette
1468 ubyte palette[256*3];
1469 ubyte colormap[256];
1472 cfread(palette,3,256,fontfile); //read the palette
1474 #ifdef SWAP_0_255 // swap the first and last palette entries (black and white)
1479 for (i = 0; i < 3; i++) {
1481 palette[i] = palette[765+i];
1485 // we also need to swap the data entries as well. black is white and white is black
1487 for (i = 0; i < ptr-font->ft_data; i++) {
1488 if (font->ft_data[i] == 0)
1489 font->ft_data[i] = 255;
1490 else if (font->ft_data[i] == 255)
1491 font->ft_data[i] = 0;
1497 build_colormap_good( (ubyte *)&palette, colormap, freq );
1499 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255 to this for macintosh
1501 decode_data_asm(font->ft_data, (int)(ptr - font->ft_data), colormap, freq );
1515 char tests[]="abcdefghij1234.A";
1516 gr_get_string_size(tests,&x,&y,&aw);
1517 // newfont->ft_aw=x/(float)strlen(tests);
1521 ogl_init_font(font);
1528 //remap a font by re-reading its data & palette
1529 void gr_remap_font( grs_font *font, char * fontname, char *font_data )
1535 int datasize; //size up to (but not including) palette
1538 if (! (font->ft_flags & FT_COLOR))
1541 fontfile = cfopen(fontname, "rb");
1544 Error( "Can't open font file %s", fontname );
1546 cfread(file_id, 4, 1, fontfile);
1547 if ( !strncmp( file_id, "NFSP", 4 ) )
1548 Error( "File %s is not a font file", fontname );
1550 datasize = cfile_read_int(fontfile);
1551 datasize -= GRS_FONT_SIZE; // subtract the size of the header.
1553 d_free(font->ft_chars);
1554 grs_font_read(font, fontfile); // have to reread in case mission hogfile overrides font.
1556 cfread(font_data, 1, datasize, fontfile); //read raw data
1558 // make these offsets relative to font_data
1559 font->ft_data = (ubyte *)((int)font->ft_data - GRS_FONT_SIZE);
1560 font->ft_widths = (short *)((int)font->ft_widths - GRS_FONT_SIZE);
1561 font->ft_kerndata = (ubyte *)((int)font->ft_kerndata - GRS_FONT_SIZE);
1563 nchars = font->ft_maxchar - font->ft_minchar + 1;
1565 if (font->ft_flags & FT_PROPORTIONAL) {
1567 font->ft_widths = (short *) &font_data[(int)font->ft_widths];
1568 font->ft_data = (unsigned char *) &font_data[(int)font->ft_data];
1569 font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1571 ptr = font->ft_data;
1573 for (i=0; i< nchars; i++ ) {
1574 font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]);
1575 font->ft_chars[i] = ptr;
1576 if (font->ft_flags & FT_COLOR)
1577 ptr += font->ft_widths[i] * font->ft_h;
1579 ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1584 font->ft_data = (unsigned char *) font_data;
1585 font->ft_chars = NULL;
1586 font->ft_widths = NULL;
1588 ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1591 if (font->ft_flags & FT_KERNED)
1592 font->ft_kerndata = (unsigned char *) &font_data[(int)font->ft_kerndata];
1594 if (font->ft_flags & FT_COLOR) { //remap palette
1595 ubyte palette[256*3];
1596 ubyte colormap[256];
1599 cfread(palette,3,256,fontfile); //read the palette
1601 #ifdef SWAP_0_255 // swap the first and last palette entries (black and white)
1606 for (i = 0; i < 3; i++) {
1608 palette[i] = palette[765+i];
1612 // we also need to swap the data entries as well. black is white and white is black
1614 for (i = 0; i < ptr-font->ft_data; i++) {
1615 if (font->ft_data[i] == 0)
1616 font->ft_data[i] = 255;
1617 else if (font->ft_data[i] == 255)
1618 font->ft_data[i] = 0;
1624 build_colormap_good( (ubyte *)&palette, colormap, freq );
1626 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255 to this for macintosh
1628 decode_data_asm(font->ft_data, (int)(ptr - font->ft_data), colormap, freq );
1635 if (font->ft_bitmaps)
1636 d_free( font->ft_bitmaps );
1637 gr_free_bitmap_data(&font->ft_parent_bitmap);
1638 // ogl_freebmtexture(&font->ft_parent_bitmap);
1640 ogl_init_font(font);
1645 void gr_set_fontcolor( int fg, int bg )
1651 void gr_set_curfont( grs_font * new )
1657 int gr_internal_string_clipped(int x, int y, char *s )
1660 char * text_ptr, * next_row, * text_ptr1;
1661 int r, BitMask, i, bits, width, spacing, letter, underline;
1668 while (next_row != NULL )
1670 text_ptr1 = next_row;
1674 if (x==0x8000) //centered
1675 x = get_centered_x(text_ptr1);
1679 for (r=0; r<FHEIGHT; r++) {
1680 text_ptr = text_ptr1;
1684 if (*text_ptr == '\n' ) {
1685 next_row = &text_ptr[1];
1689 if (*text_ptr == CC_COLOR) {
1690 FG_COLOR = *(text_ptr+1);
1695 if (*text_ptr == CC_LSPACING) {
1696 Int3(); // Warning: skip lines not supported for clipped strings.
1702 if (*text_ptr == CC_UNDERLINE ) {
1703 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1708 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1710 letter = *text_ptr-FMINCHAR;
1712 if (!INFONT(letter)) { //not in font, draw as space
1718 if (FFLAGS & FT_PROPORTIONAL)
1719 fp = FCHARS[letter];
1721 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1724 for (i=0; i< width; i++ ) {
1725 gr_setcolor(FG_COLOR);
1729 fp += BITS_TO_BYTES(width)*r;
1733 for (i=0; i< width; i++ ) {
1739 gr_setcolor(FG_COLOR);
1741 gr_setcolor(BG_COLOR);
1747 x += spacing-width; //for kerning
1757 int gr_internal_string_clipped_m(int x, int y, char *s )
1760 char * text_ptr, * next_row, * text_ptr1;
1761 int r, BitMask, i, bits, width, spacing, letter, underline;
1768 while (next_row != NULL )
1770 text_ptr1 = next_row;
1774 if (x==0x8000) //centered
1775 x = get_centered_x(text_ptr1);
1779 for (r=0; r<FHEIGHT; r++) {
1782 text_ptr = text_ptr1;
1785 if (*text_ptr == '\n' ) {
1786 next_row = &text_ptr[1];
1790 if (*text_ptr == CC_COLOR) {
1791 FG_COLOR = *(text_ptr+1);
1796 if (*text_ptr == CC_LSPACING) {
1797 Int3(); // Warning: skip lines not supported for clipped strings.
1803 if (*text_ptr == CC_UNDERLINE ) {
1804 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1809 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1811 letter = *text_ptr-FMINCHAR;
1813 if (!INFONT(letter)) { //not in font, draw as space
1819 if (FFLAGS & FT_PROPORTIONAL)
1820 fp = FCHARS[letter];
1822 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1825 for (i=0; i< width; i++ ) {
1826 gr_setcolor(FG_COLOR);
1830 fp += BITS_TO_BYTES(width)*r;
1834 for (i=0; i< width; i++ ) {
1839 if (bits & BitMask) {
1840 gr_setcolor(FG_COLOR);
1849 x += spacing-width; //for kerning