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)
43 #define MAX_OPEN_FONTS 50
44 #define FILENAME_LEN 13
46 typedef struct openfont {
47 char filename[FILENAME_LEN];
52 //list of open fonts, for use (for now) for palette remapping
53 openfont open_font[MAX_OPEN_FONTS];
55 #define FONT grd_curcanv->cv_font
56 #define FG_COLOR grd_curcanv->cv_font_fg_color
57 #define BG_COLOR grd_curcanv->cv_font_bg_color
58 #define FWIDTH FONT->ft_w
59 #define FHEIGHT FONT->ft_h
60 #define FBASELINE FONT->ft_baseline
61 #define FFLAGS FONT->ft_flags
62 #define FMINCHAR FONT->ft_minchar
63 #define FMAXCHAR FONT->ft_maxchar
64 #define FDATA FONT->ft_data
65 #define FCHARS FONT->ft_chars
66 #define FWIDTHS FONT->ft_widths
68 #define BITS_TO_BYTES(x) (((x)+7)>>3)
70 int gr_internal_string_clipped(int x, int y, const char *s );
71 int gr_internal_string_clipped_m(int x, int y, const char *s );
73 ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second)
75 ubyte *p=font->ft_kerndata;
78 if (p[0]==first && p[1]==second)
86 //takes the character AFTER being offset into font
87 #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
89 //takes the character BEFORE being offset into current font
90 void get_char_width(ubyte c,ubyte c2,int *width,int *spacing)
96 if (!INFONT(letter)) { //not in font, draw as space
98 if (FFLAGS & FT_PROPORTIONAL)
105 if (FFLAGS & FT_PROPORTIONAL)
106 *width = FWIDTHS[letter];
112 if (FFLAGS & FT_KERNED) {
115 if (!(c2==0 || c2=='\n')) {
118 letter2 = c2-FMINCHAR;
120 if (INFONT(letter2)) {
122 p = find_kern_entry(FONT,(ubyte)letter,letter2);
131 int get_centered_x(const char *s)
135 for (w=0;*s!=0 && *s!='\n';s++) {
139 continue;//skip color codes.
141 get_char_width(s[0],s[1],&w2,&s2);
145 return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
148 //hack to allow color codes to be embedded in strings -MPM
149 //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string.
150 //function must already have orig_color var set (or they could be passed as args...)
151 //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain
152 int gr_message_color_level=1;
153 #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x03)) { \
156 if (gr_message_color_level >= *(text_ptr-1)) \
157 FG_COLOR = *text_ptr - 1; \
161 else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \
162 if (gr_message_color_level >= *text_ptr - 3) \
163 FG_COLOR=orig_color; \
167 int gr_internal_string0(int x, int y, const char *s )
170 const char * text_ptr, * next_row, * text_ptr1;
171 int r, BitMask, i, bits, width, spacing, letter, underline;
174 unsigned int VideoOffset, VideoOffset1;
178 VideoOffset1 = y * ROWSIZE + x;
182 while (next_row != NULL )
184 text_ptr1 = next_row;
187 if (x==0x8000) { //centered
188 int xx = get_centered_x(text_ptr1);
189 VideoOffset1 = y * ROWSIZE + xx;
192 for (r=0; r<FHEIGHT; r++)
195 text_ptr = text_ptr1;
197 VideoOffset = VideoOffset1;
201 if (*text_ptr == '\n' )
203 next_row = &text_ptr[1];
207 if (*text_ptr == CC_COLOR) {
208 FG_COLOR = *(text_ptr+1);
213 if (*text_ptr == CC_LSPACING) {
214 skip_lines = *(text_ptr+1) - '0';
220 if (*text_ptr == CC_UNDERLINE )
222 if ((r==FBASELINE+2) || (r==FBASELINE+3))
227 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
229 letter = (unsigned char)*text_ptr - FMINCHAR;
231 if (!INFONT(letter)) { //not in font, draw as space
232 VideoOffset += spacing;
237 if (FFLAGS & FT_PROPORTIONAL)
240 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
243 for (i=0; i< width; i++ )
244 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
247 fp += BITS_TO_BYTES(width)*r;
251 for (i=0; i< width; i++ )
259 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
261 DATA[VideoOffset++] = (unsigned char) BG_COLOR;
266 VideoOffset += spacing-width; //for kerning
271 VideoOffset1 += ROWSIZE; y++;
275 VideoOffset1 += ROWSIZE * skip_lines;
281 int gr_internal_string0m(int x, int y, const char *s )
284 const char * text_ptr, * next_row, * text_ptr1;
285 int r, BitMask, i, bits, width, spacing, letter, underline;
288 unsigned int VideoOffset, VideoOffset1;
290 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
294 VideoOffset1 = y * ROWSIZE + x;
298 while (next_row != NULL )
300 text_ptr1 = next_row;
303 if (x==0x8000) { //centered
304 int xx = get_centered_x(text_ptr1);
305 VideoOffset1 = y * ROWSIZE + xx;
308 for (r=0; r<FHEIGHT; r++)
311 text_ptr = text_ptr1;
313 VideoOffset = VideoOffset1;
317 if (*text_ptr == '\n' )
319 next_row = &text_ptr[1];
323 if (*text_ptr == CC_COLOR) {
324 FG_COLOR = *(text_ptr+1);
329 if (*text_ptr == CC_LSPACING) {
330 skip_lines = *(text_ptr+1) - '0';
336 if (*text_ptr == CC_UNDERLINE )
338 if ((r==FBASELINE+2) || (r==FBASELINE+3))
343 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
345 letter = (unsigned char)*text_ptr-FMINCHAR;
347 if (!INFONT(letter) || (unsigned char) *text_ptr <= 0x06) //not in font, draw as space
349 CHECK_EMBEDDED_COLORS() else{
350 VideoOffset += spacing;
356 if (FFLAGS & FT_PROPORTIONAL)
359 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
362 for (i=0; i< width; i++ )
363 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
366 fp += BITS_TO_BYTES(width)*r;
370 for (i=0; i< width; i++ )
378 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
386 VideoOffset += spacing-width;
389 VideoOffset1 += ROWSIZE;
393 VideoOffset1 += ROWSIZE * skip_lines;
400 int gr_internal_string2(int x, int y, char *s )
403 ubyte * text_ptr, * next_row, * text_ptr1;
404 int r, BitMask, i, bits, width, spacing, letter, underline;
405 int page_switched, skip_lines = 0;
407 unsigned int VideoOffset, VideoOffset1;
409 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
413 gr_vesa_setpage(VideoOffset1 >> 16);
415 VideoOffset1 &= 0xFFFF;
419 while (next_row != NULL )
421 text_ptr1 = next_row;
424 if (x==0x8000) { //centered
425 int xx = get_centered_x(text_ptr1);
426 VideoOffset1 = y * ROWSIZE + xx;
427 gr_vesa_setpage(VideoOffset1 >> 16);
428 VideoOffset1 &= 0xFFFF;
431 for (r=0; r<FHEIGHT; r++)
433 text_ptr = text_ptr1;
435 VideoOffset = VideoOffset1;
441 if (*text_ptr == '\n' )
443 next_row = &text_ptr[1];
447 if (*text_ptr == CC_COLOR) {
448 FG_COLOR = *(text_ptr+1);
453 if (*text_ptr == CC_LSPACING) {
454 skip_lines = *(text_ptr+1) - '0';
460 if (*text_ptr == CC_UNDERLINE )
462 if ((r==FBASELINE+2) || (r==FBASELINE+3))
467 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
469 Assert(width==spacing); //no kerning support here
471 letter = *text_ptr-FMINCHAR;
473 if (!INFONT(letter)) { //not in font, draw as space
474 VideoOffset += spacing;
479 if (FFLAGS & FT_PROPORTIONAL)
482 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
486 if ( VideoOffset+width > 0xFFFF )
488 for (i=0; i< width; i++ )
490 gr_video_memory[VideoOffset++] = FG_COLOR;
492 if (VideoOffset > 0xFFFF )
494 VideoOffset -= 0xFFFF + 1;
502 for (i=0; i< width; i++ )
503 gr_video_memory[VideoOffset++] = FG_COLOR;
512 fp += BITS_TO_BYTES(width)*r;
516 if ( VideoOffset+width > 0xFFFF )
518 for (i=0; i< width; i++ )
526 gr_video_memory[VideoOffset++] = FG_COLOR;
528 gr_video_memory[VideoOffset++] = BG_COLOR;
532 if (VideoOffset > 0xFFFF )
534 VideoOffset -= 0xFFFF + 1;
546 if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR;
547 else gr_video_memory[VideoOffset+0] = BG_COLOR;
549 if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR;
550 else gr_video_memory[VideoOffset+1] = BG_COLOR;
552 if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR;
553 else gr_video_memory[VideoOffset+2] = BG_COLOR;
555 if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR;
556 else gr_video_memory[VideoOffset+3] = BG_COLOR;
558 if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR;
559 else gr_video_memory[VideoOffset+4] = BG_COLOR;
561 if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR;
562 else gr_video_memory[VideoOffset+5] = BG_COLOR;
564 if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR;
565 else gr_video_memory[VideoOffset+6] = BG_COLOR;
567 if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR;
568 else gr_video_memory[VideoOffset+7] = BG_COLOR;
572 for (i=0; i< width/2 ; i++ )
580 gr_video_memory[VideoOffset++] = FG_COLOR;
582 gr_video_memory[VideoOffset++] = BG_COLOR;
594 gr_video_memory[VideoOffset++] = FG_COLOR;
596 gr_video_memory[VideoOffset++] = BG_COLOR;
606 VideoOffset1 += ROWSIZE;
608 if (VideoOffset1 > 0xFFFF ) {
609 VideoOffset1 -= 0xFFFF + 1;
616 VideoOffset1 += ROWSIZE * skip_lines;
622 int gr_internal_string2m(int x, int y, char *s )
625 unsigned char * text_ptr, * next_row, * text_ptr1;
626 int r, BitMask, i, bits, width, spacing, letter, underline;
627 int page_switched, skip_lines = 0;
629 unsigned int VideoOffset, VideoOffset1;
631 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
633 gr_vesa_setpage(VideoOffset1 >> 16);
635 VideoOffset1 &= 0xFFFF;
639 while (next_row != NULL )
641 text_ptr1 = next_row;
644 if (x==0x8000) { //centered
645 int xx = get_centered_x(text_ptr1);
646 VideoOffset1 = y * ROWSIZE + xx;
647 gr_vesa_setpage(VideoOffset1 >> 16);
648 VideoOffset1 &= 0xFFFF;
651 for (r=0; r<FHEIGHT; r++)
653 text_ptr = text_ptr1;
655 VideoOffset = VideoOffset1;
661 if (*text_ptr == '\n' )
663 next_row = &text_ptr[1];
667 if (*text_ptr == CC_COLOR) {
668 FG_COLOR = *(text_ptr+1);
673 if (*text_ptr == CC_LSPACING) {
674 skip_lines = *(text_ptr+1) - '0';
680 if (*text_ptr == CC_UNDERLINE )
682 if ((r==FBASELINE+2) || (r==FBASELINE+3))
687 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
689 letter = *text_ptr-FMINCHAR;
691 if (!INFONT(letter)) { //not in font, draw as space
692 VideoOffset += width;
697 if (FFLAGS & FT_PROPORTIONAL)
700 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
704 if ( VideoOffset+width > 0xFFFF )
706 for (i=0; i< width; i++ )
708 gr_video_memory[VideoOffset++] = FG_COLOR;
710 if (VideoOffset > 0xFFFF )
712 VideoOffset -= 0xFFFF + 1;
720 for (i=0; i< width; i++ )
721 gr_video_memory[VideoOffset++] = FG_COLOR;
726 fp += BITS_TO_BYTES(width)*r;
730 if ( VideoOffset+width > 0xFFFF )
732 for (i=0; i< width; i++ )
740 gr_video_memory[VideoOffset++] = FG_COLOR;
746 if (VideoOffset > 0xFFFF )
748 VideoOffset -= 0xFFFF + 1;
755 for (i=0; i< width; i++ )
763 gr_video_memory[VideoOffset++] = FG_COLOR;
772 VideoOffset += spacing-width;
776 VideoOffset1 += ROWSIZE;
778 if (VideoOffset1 > 0xFFFF ) {
779 VideoOffset1 -= 0xFFFF + 1;
786 VideoOffset1 += ROWSIZE * skip_lines;
795 //a bitmap for the character
796 grs_bitmap char_bm = {
799 BM_FLAG_TRANSPARENT, //flags
802 #ifdef BITMAP_SELECTOR
809 int gr_internal_color_string(int x, int y, const char *s )
812 const char *text_ptr, *next_row, *text_ptr1;
813 int width, spacing,letter;
816 char_bm.bm_h = FHEIGHT; //set height for chars of this font
823 while (next_row != NULL)
825 text_ptr1 = next_row;
828 text_ptr = text_ptr1;
832 if (xx==0x8000) //centered
833 xx = get_centered_x(text_ptr);
837 if (*text_ptr == '\n' )
839 next_row = &text_ptr[1];
844 letter = (unsigned char)*text_ptr - FMINCHAR;
846 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
848 if (!INFONT(letter)) { //not in font, draw as space
854 if (FFLAGS & FT_PROPORTIONAL)
857 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
859 gr_init_bitmap (&char_bm, BM_LINEAR, 0, 0, width, FHEIGHT, width, fp);
860 gr_bitmapm(xx,yy,&char_bm);
873 #include "ogl_init.h"
875 //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
877 int pow2ize(int x);//from ogl.c
879 int get_font_total_width(grs_font * font){
880 if (font->ft_flags & FT_PROPORTIONAL){
881 int i,w=0,c=font->ft_minchar;
882 for (i=0;c<=font->ft_maxchar;i++,c++){
883 if (font->ft_widths[i]<0)
885 w+=font->ft_widths[i];
889 return font->ft_w*(font->ft_maxchar-font->ft_minchar+1);
892 void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){
893 int nchars = font->ft_maxchar-font->ft_minchar+1;
894 int r,x,y,nc=0,smallest=999999,smallr=-1,tries;
897 for (h=32;h<=256;h*=2){
898 // h=pow2ize(font->ft_h*rows+gap*(rows-1));
899 if (font->ft_h>h)continue;
900 r=(h/(font->ft_h+gap));
901 w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r);
907 mprintf((0,"failed to fit (%ix%i, %ic)\n",w,h,nc));
912 while(y+font->ft_h<=h){
917 if (font->ft_flags & FT_PROPORTIONAL){
918 if (x+font->ft_widths[nc]+gap>w)break;
919 x+=font->ft_widths[nc++]+gap;
921 if (x+font->ft_w+gap>w)break;
935 mprintf((0,"fit: %ix%i %i tries\n",w,h,tries));
937 if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32)
958 Error("couldn't fit font?\n");
959 mprintf((0,"using %ix%i\n",*rw,*rh));
963 void ogl_init_font(grs_font * font){
964 int oglflags = OGL_FLAG_ALPHA;
965 int nchars = font->ft_maxchar-font->ft_minchar+1;
966 int i,w,h,tw,th,x,y,curx=0,cury=0;
968 // char data[32*32*4];
970 int gap=0;//having a gap just wastes ram, since we don't filter text textures at all.
972 ogl_font_choose_size(font,gap,&tw,&th);
973 data=d_malloc(tw*th);
974 memset(data, 0, tw * th);
975 gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data);
976 gr_set_transparent(&font->ft_parent_bitmap, 1);
978 if (!(font->ft_flags & FT_COLOR))
979 oglflags |= OGL_FLAG_NOCOLOR;
980 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.
982 font->ft_bitmaps=(grs_bitmap*)d_malloc( nchars * sizeof(grs_bitmap));
983 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));
988 for(i=0;i<nchars;i++){
989 // s[0]=font->ft_minchar+i;
990 // gr_get_string_size(s,&w,&h,&aw);
991 if (font->ft_flags & FT_PROPORTIONAL)
992 w=font->ft_widths[i];
995 // mprintf((0,"char %i(%ix%i): ",i,w,h));
997 mprintf((0,"grr\n"));continue;
1004 Error("font doesn't really fit (%i/%i)?\n",i,nchars);
1005 if (font->ft_flags & FT_COLOR) {
1006 if (font->ft_flags & FT_PROPORTIONAL)
1007 fp = font->ft_chars[i];
1009 fp = font->ft_data + i * w*h;
1012 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w];
1015 // gr_init_bitmap(&font->ft_bitmaps[i],BM_LINEAR,0,0,w,h,w,font->);
1017 int BitMask,bits=0,white=gr_find_closest_color(63,63,63);
1018 // if (w*h>sizeof(data))
1019 // Error("ogl_init_font: toobig\n");
1020 if (font->ft_flags & FT_PROPORTIONAL)
1021 fp = font->ft_chars[i];
1023 fp = font->ft_data + i * BITS_TO_BYTES(w)*h;
1026 for (x=0; x< w; x++ )
1034 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white;
1036 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255;
1041 gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h);
1045 ogl_loadbmtexture_f(&font->ft_parent_bitmap, oglflags);
1048 int ogl_internal_string(int x, int y, const char *s )
1050 const char * text_ptr, * next_row, * text_ptr1;
1051 int width, spacing,letter;
1053 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
1060 if (grd_curscreen->sc_canvas.cv_bitmap.bm_type != BM_OGL)
1062 while (next_row != NULL)
1064 text_ptr1 = next_row;
1067 text_ptr = text_ptr1;
1071 if (xx==0x8000) //centered
1072 xx = get_centered_x(text_ptr);
1076 if (*text_ptr == '\n' )
1078 next_row = &text_ptr[1];
1083 if (*text_ptr == CC_LSPACING) {
1084 skip_lines = *(text_ptr+1) - '0';
1089 if (*text_ptr == CC_UNDERLINE ) {
1094 letter = (unsigned char)*text_ptr - FMINCHAR;
1096 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1098 if (!INFONT(letter) || (unsigned char)*text_ptr <= 0x06)
1099 { //not in font, draw as space
1100 CHECK_EMBEDDED_COLORS() else{
1107 // ogl_ubitblt(FONT->ft_bitmaps[letter].bm_w,FONT->ft_bitmaps[letter].bm_h,xx,yy,0,0,&FONT->ft_bitmaps[letter],NULL);
1108 // if (*text_ptr>='0' && *text_ptr<='9'){
1109 if (FFLAGS&FT_COLOR)
1110 gr_bitmapm(xx, yy, &FONT->ft_bitmaps[letter]);
1112 if (grd_curcanv->cv_bitmap.bm_type==BM_OGL)
1113 ogl_ubitmapm_c(xx,yy,&FONT->ft_bitmaps[letter],FG_COLOR);
1115 Error("ogl_internal_string: non-color string to non-ogl dest\n");
1116 // gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);//ignores color..
1131 int gr_internal_color_string(int x, int y, const char *s ){
1132 return ogl_internal_string(x,y,s);
1136 int gr_string(int x, int y, const char *s )
1141 Assert(FONT != NULL);
1143 if ( x == 0x8000 ) {
1144 if ( y<0 ) clipped |= 1;
1145 gr_get_string_size(s, &w, &h, &aw );
1146 // for x, since this will be centered, only look at
1148 if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1149 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1151 if ( (y+h) < 0 ) clipped |= 2;
1152 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1155 if ( (x<0) || (y<0) ) clipped |= 1;
1156 gr_get_string_size(s, &w, &h, &aw );
1157 if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1158 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1159 if ( (x+w) < 0 ) clipped |= 2;
1160 if ( (y+h) < 0 ) clipped |= 2;
1161 if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;
1162 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1166 return gr_ustring(x, y, s );
1168 if ( clipped & 2 ) {
1169 // Completely clipped...
1170 mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
1174 if ( clipped & 1 ) {
1175 // Partially clipped...
1176 //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
1179 // Partially clipped...
1182 return ogl_internal_string(x,y,s);
1185 if (FFLAGS & FT_COLOR)
1186 return gr_internal_color_string( x, y, s);
1188 if ( BG_COLOR == -1)
1189 return gr_internal_string_clipped_m( x, y, s );
1191 return gr_internal_string_clipped( x, y, s );
1194 int gr_ustring(int x, int y, const char *s )
1198 return ogl_internal_string(x,y,s);
1201 if (FFLAGS & FT_COLOR) {
1203 return gr_internal_color_string(x,y,s);
1210 if ( BG_COLOR == -1)
1211 return gr_internal_string0m(x,y,s);
1213 return gr_internal_string0(x,y,s);
1216 if ( BG_COLOR == -1)
1217 return gr_internal_string2m(x,y,s);
1219 return gr_internal_string2(x,y,s);
1226 void gr_get_string_size(const char *s, int *string_width, int *string_height, int *average_width )
1228 int i = 0, longest_width = 0;
1231 *string_height = FHEIGHT;
1233 *average_width = FWIDTH;
1240 // if (*s == CC_UNDERLINE)
1245 *string_height += FHEIGHT;
1251 // 1 = next byte specifies color, so skip the 1 and the color value
1254 else if (*s == CC_LSPACING) {
1255 *string_height += *(s+1)-'0';
1258 get_char_width(s[0],s[1],&width,&spacing);
1260 *string_width += spacing;
1262 if (*string_width > longest_width)
1263 longest_width = *string_width;
1270 *string_width = longest_width;
1274 int gr_uprintf( int x, int y, const char * format, ... )
1279 va_start(args, format );
1280 vsprintf(buffer,format,args);
1281 return gr_ustring( x, y, buffer );
1284 int gr_printf( int x, int y, const char * format, ... )
1289 va_start(args, format );
1290 vsprintf(buffer,format,args);
1291 return gr_string( x, y, buffer );
1294 void gr_close_font( grs_font * font )
1302 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=font;fontnum++);
1303 Assert(fontnum<MAX_OPEN_FONTS); //did we find slot?
1305 font_data = open_font[fontnum].dataptr;
1306 d_free( font_data );
1308 open_font[fontnum].ptr = NULL;
1309 open_font[fontnum].dataptr = NULL;
1311 if ( font->ft_chars )
1312 d_free( font->ft_chars );
1314 if (font->ft_bitmaps)
1315 d_free( font->ft_bitmaps );
1316 gr_free_bitmap_data(&font->ft_parent_bitmap);
1317 // ogl_freebmtexture(&font->ft_parent_bitmap);
1325 //remap (by re-reading) all the color fonts
1326 void gr_remap_color_fonts()
1330 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1333 font = open_font[fontnum].ptr;
1335 if (font && (font->ft_flags & FT_COLOR))
1336 gr_remap_font(font, open_font[fontnum].filename, open_font[fontnum].dataptr);
1340 void gr_remap_mono_fonts()
1343 con_printf (CON_DEBUG, "gr_remap_mono_fonts ()\n");
1344 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1346 font = open_font[fontnum].ptr;
1347 if (font && !(font->ft_flags & FT_COLOR))
1348 gr_remap_font(font, open_font[fontnum].filename, open_font[fontnum].dataptr);
1353 #define grs_font_read(gf, fp) cfread(gf, GRS_FONT_SIZE, 1, fp)
1356 * reads a grs_font structure from a CFILE
1358 void grs_font_read(grs_font *gf, CFILE *fp)
1360 gf->ft_w = cfile_read_short(fp);
1361 gf->ft_h = cfile_read_short(fp);
1362 gf->ft_flags = cfile_read_short(fp);
1363 gf->ft_baseline = cfile_read_short(fp);
1364 gf->ft_minchar = cfile_read_byte(fp);
1365 gf->ft_maxchar = cfile_read_byte(fp);
1366 gf->ft_bytewidth = cfile_read_short(fp);
1367 gf->ft_data = (ubyte *)(size_t)cfile_read_int(fp);
1368 gf->ft_chars = (ubyte **)(size_t)cfile_read_int(fp);
1369 gf->ft_widths = (short *)(size_t)cfile_read_int(fp);
1370 gf->ft_kerndata = (ubyte *)(size_t)cfile_read_int(fp);
1374 grs_font * gr_init_font( const char * fontname )
1376 static int first_time=1;
1380 unsigned char * ptr;
1384 int datasize; //size up to (but not including) palette
1388 for (i=0;i<MAX_OPEN_FONTS;i++)
1390 open_font[i].ptr = NULL;
1391 open_font[i].dataptr = NULL;
1396 //find free font slot
1397 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=NULL;fontnum++);
1398 Assert(fontnum<MAX_OPEN_FONTS); //did we find one?
1400 strncpy(open_font[fontnum].filename,fontname,FILENAME_LEN);
1402 fontfile = cfopen(fontname, "rb");
1405 con_printf(CON_VERBOSE, "Can't open font file %s\n", fontname);
1409 cfread(file_id, 4, 1, fontfile);
1410 if ( !strncmp( file_id, "NFSP", 4 ) ) {
1411 con_printf(CON_NORMAL, "File %s is not a font file\n", fontname );
1415 datasize = cfile_read_int(fontfile);
1416 datasize -= GRS_FONT_SIZE; // subtract the size of the header.
1418 MALLOC(font, grs_font, sizeof(grs_font));
1419 grs_font_read(font, fontfile);
1421 MALLOC(font_data, char, datasize);
1422 cfread(font_data, 1, datasize, fontfile);
1424 open_font[fontnum].ptr = font;
1425 open_font[fontnum].dataptr = font_data;
1427 // make these offsets relative to font_data
1428 font->ft_data = (ubyte *)((size_t)font->ft_data - GRS_FONT_SIZE);
1429 font->ft_widths = (short *)((size_t)font->ft_widths - GRS_FONT_SIZE);
1430 font->ft_kerndata = (ubyte *)((size_t)font->ft_kerndata - GRS_FONT_SIZE);
1432 nchars = font->ft_maxchar - font->ft_minchar + 1;
1434 if (font->ft_flags & FT_PROPORTIONAL) {
1436 font->ft_widths = (short *) &font_data[(size_t)font->ft_widths];
1437 font->ft_data = (unsigned char *) &font_data[(size_t)font->ft_data];
1438 font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1440 ptr = font->ft_data;
1442 for (i=0; i< nchars; i++ ) {
1443 font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]);
1444 font->ft_chars[i] = ptr;
1445 if (font->ft_flags & FT_COLOR)
1446 ptr += font->ft_widths[i] * font->ft_h;
1448 ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1453 font->ft_data = (unsigned char *) font_data;
1454 font->ft_chars = NULL;
1455 font->ft_widths = NULL;
1457 ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1460 if (font->ft_flags & FT_KERNED)
1461 font->ft_kerndata = (unsigned char *) &font_data[(size_t)font->ft_kerndata];
1463 if (font->ft_flags & FT_COLOR) { //remap palette
1464 ubyte palette[256*3];
1465 ubyte colormap[256];
1468 cfread(palette,3,256,fontfile); //read the palette
1470 #ifdef SWAP_0_255 // swap the first and last palette entries (black and white)
1475 for (i = 0; i < 3; i++) {
1477 palette[i] = palette[765+i];
1481 // we also need to swap the data entries as well. black is white and white is black
1483 for (i = 0; i < ptr-font->ft_data; i++) {
1484 if (font->ft_data[i] == 0)
1485 font->ft_data[i] = 255;
1486 else if (font->ft_data[i] == 255)
1487 font->ft_data[i] = 0;
1493 build_colormap_good( (ubyte *)&palette, colormap, freq );
1495 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255 to this for macintosh
1497 decode_data_asm(font->ft_data, (int)(ptr - font->ft_data), colormap, freq );
1510 char tests[]="abcdefghij1234.A";
1511 gr_get_string_size(tests,&x,&y,&aw);
1512 // newfont->ft_aw=x/(float)strlen(tests);
1516 ogl_init_font(font);
1523 //remap a font by re-reading its data & palette
1524 void gr_remap_font( grs_font *font, char * fontname, char *font_data )
1530 int datasize; //size up to (but not including) palette
1533 if (! (font->ft_flags & FT_COLOR))
1536 fontfile = cfopen(fontname, "rb");
1539 Error( "Can't open font file %s", fontname );
1541 cfread(file_id, 4, 1, fontfile);
1542 if ( !strncmp( file_id, "NFSP", 4 ) )
1543 Error( "File %s is not a font file", fontname );
1545 datasize = cfile_read_int(fontfile);
1546 datasize -= GRS_FONT_SIZE; // subtract the size of the header.
1548 d_free(font->ft_chars);
1549 grs_font_read(font, fontfile); // have to reread in case mission hogfile overrides font.
1551 cfread(font_data, 1, datasize, fontfile); //read raw data
1553 // make these offsets relative to font_data
1554 font->ft_data = (ubyte *)((size_t)font->ft_data - GRS_FONT_SIZE);
1555 font->ft_widths = (short *)((size_t)font->ft_widths - GRS_FONT_SIZE);
1556 font->ft_kerndata = (ubyte *)((size_t)font->ft_kerndata - GRS_FONT_SIZE);
1558 nchars = font->ft_maxchar - font->ft_minchar + 1;
1560 if (font->ft_flags & FT_PROPORTIONAL) {
1562 font->ft_widths = (short *) &font_data[(size_t)font->ft_widths];
1563 font->ft_data = (unsigned char *) &font_data[(size_t)font->ft_data];
1564 font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1566 ptr = font->ft_data;
1568 for (i=0; i< nchars; i++ ) {
1569 font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]);
1570 font->ft_chars[i] = ptr;
1571 if (font->ft_flags & FT_COLOR)
1572 ptr += font->ft_widths[i] * font->ft_h;
1574 ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1579 font->ft_data = (unsigned char *) font_data;
1580 font->ft_chars = NULL;
1581 font->ft_widths = NULL;
1583 ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1586 if (font->ft_flags & FT_KERNED)
1587 font->ft_kerndata = (unsigned char *) &font_data[(size_t)font->ft_kerndata];
1589 if (font->ft_flags & FT_COLOR) { //remap palette
1590 ubyte palette[256*3];
1591 ubyte colormap[256];
1594 cfread(palette,3,256,fontfile); //read the palette
1596 #ifdef SWAP_0_255 // swap the first and last palette entries (black and white)
1601 for (i = 0; i < 3; i++) {
1603 palette[i] = palette[765+i];
1607 // we also need to swap the data entries as well. black is white and white is black
1609 for (i = 0; i < ptr-font->ft_data; i++) {
1610 if (font->ft_data[i] == 0)
1611 font->ft_data[i] = 255;
1612 else if (font->ft_data[i] == 255)
1613 font->ft_data[i] = 0;
1619 build_colormap_good( (ubyte *)&palette, colormap, freq );
1621 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255 to this for macintosh
1623 decode_data_asm(font->ft_data, (int)(ptr - font->ft_data), colormap, freq );
1630 if (font->ft_bitmaps)
1631 d_free( font->ft_bitmaps );
1632 gr_free_bitmap_data(&font->ft_parent_bitmap);
1633 // ogl_freebmtexture(&font->ft_parent_bitmap);
1635 ogl_init_font(font);
1640 void gr_set_fontcolor( int fg, int bg )
1646 void gr_set_curfont( grs_font * new )
1652 int gr_internal_string_clipped(int x, int y, const char *s)
1655 const char * text_ptr, * next_row, * text_ptr1;
1656 int r, BitMask, i, bits, width, spacing, letter, underline;
1663 while (next_row != NULL )
1665 text_ptr1 = next_row;
1669 if (x==0x8000) //centered
1670 x = get_centered_x(text_ptr1);
1674 for (r=0; r<FHEIGHT; r++) {
1675 text_ptr = text_ptr1;
1679 if (*text_ptr == '\n' ) {
1680 next_row = &text_ptr[1];
1684 if (*text_ptr == CC_COLOR) {
1685 FG_COLOR = *(text_ptr+1);
1690 if (*text_ptr == CC_LSPACING) {
1691 Int3(); // Warning: skip lines not supported for clipped strings.
1697 if (*text_ptr == CC_UNDERLINE ) {
1698 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1703 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1705 letter = *text_ptr-FMINCHAR;
1707 if (!INFONT(letter)) { //not in font, draw as space
1713 if (FFLAGS & FT_PROPORTIONAL)
1714 fp = FCHARS[letter];
1716 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1719 for (i=0; i< width; i++ ) {
1720 gr_setcolor(FG_COLOR);
1724 fp += BITS_TO_BYTES(width)*r;
1728 for (i=0; i< width; i++ ) {
1734 gr_setcolor(FG_COLOR);
1736 gr_setcolor(BG_COLOR);
1742 x += spacing-width; //for kerning
1752 int gr_internal_string_clipped_m(int x, int y, const char *s )
1755 const char * text_ptr, * next_row, * text_ptr1;
1756 int r, BitMask, i, bits, width, spacing, letter, underline;
1763 while (next_row != NULL )
1765 text_ptr1 = next_row;
1769 if (x==0x8000) //centered
1770 x = get_centered_x(text_ptr1);
1774 for (r=0; r<FHEIGHT; r++) {
1777 text_ptr = text_ptr1;
1780 if (*text_ptr == '\n' ) {
1781 next_row = &text_ptr[1];
1785 if (*text_ptr == CC_COLOR) {
1786 FG_COLOR = *(text_ptr+1);
1791 if (*text_ptr == CC_LSPACING) {
1792 Int3(); // Warning: skip lines not supported for clipped strings.
1798 if (*text_ptr == CC_UNDERLINE ) {
1799 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1804 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1806 letter = *text_ptr-FMINCHAR;
1808 if (!INFONT(letter)) { //not in font, draw as space
1814 if (FFLAGS & FT_PROPORTIONAL)
1815 fp = FCHARS[letter];
1817 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1820 for (i=0; i< width; i++ ) {
1821 gr_setcolor(FG_COLOR);
1825 fp += BITS_TO_BYTES(width)*r;
1829 for (i=0; i< width; i++ ) {
1834 if (bits & BitMask) {
1835 gr_setcolor(FG_COLOR);
1844 x += spacing-width; //for kerning