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.
14 /* $Source: /cvs/cvsroot/d2x/2d/font.c,v $
17 * $Date: 2001-11-02 10:46:23 $
19 * Graphical routines for drawing fonts.
21 * $Log: not supported by cvs2svn $
22 * Revision 1.6 2001/11/02 02:03:35 bradleyb
23 * Enable OpenGL fonts\!
40 #include "pa_enabl.h" //$$POLY_ACC
56 #define MAX_OPEN_FONTS 50
57 #define FILENAME_LEN 13
59 typedef struct openfont {
60 char filename[FILENAME_LEN];
64 //list of open fonts, for use (for now) for palette remapping
65 openfont open_font[MAX_OPEN_FONTS];
67 #define FONT grd_curcanv->cv_font
68 #define FG_COLOR grd_curcanv->cv_font_fg_color
69 #define BG_COLOR grd_curcanv->cv_font_bg_color
70 #define FWIDTH FONT->ft_w
71 #define FHEIGHT FONT->ft_h
72 #define FBASELINE FONT->ft_baseline
73 #define FFLAGS FONT->ft_flags
74 #define FMINCHAR FONT->ft_minchar
75 #define FMAXCHAR FONT->ft_maxchar
76 #define FDATA FONT->ft_data
77 #define FCHARS FONT->ft_chars
78 #define FWIDTHS FONT->ft_widths
80 #define BITS_TO_BYTES(x) (((x)+7)>>3)
82 int gr_internal_string_clipped(int x, int y, char *s );
83 int gr_internal_string_clipped_m(int x, int y, char *s );
85 ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second)
87 ubyte *p=font->ft_kerndata;
90 if (p[0]==first && p[1]==second)
98 //takes the character AFTER being offset into font
99 #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
101 //takes the character BEFORE being offset into current font
102 void get_char_width(ubyte c,ubyte c2,int *width,int *spacing)
108 if (!INFONT(letter)) { //not in font, draw as space
110 if (FFLAGS & FT_PROPORTIONAL)
117 if (FFLAGS & FT_PROPORTIONAL)
118 *width = FWIDTHS[letter];
124 if (FFLAGS & FT_KERNED) {
127 if (!(c2==0 || c2=='\n')) {
130 letter2 = c2-FMINCHAR;
132 if (INFONT(letter2)) {
134 p = find_kern_entry(FONT,(ubyte)letter,letter2);
143 int get_centered_x(char *s)
147 for (w=0;*s!=0 && *s!='\n';s++) {
151 continue;//skip color codes.
153 get_char_width(s[0],s[1],&w2,&s2);
157 return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
160 //hack to allow color codes to be embedded in strings -MPM
161 //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string.
162 //function must already have orig_color var set (or they could be passed as args...)
163 //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain
164 int gr_message_color_level=1;
165 #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x03)) { \
168 if (gr_message_color_level >= *(text_ptr-1)) \
169 FG_COLOR = *text_ptr - 1; \
173 else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \
174 if (gr_message_color_level >= *text_ptr - 3) \
175 FG_COLOR=orig_color; \
179 int gr_internal_string0(int x, int y, char *s )
182 ubyte * text_ptr, * next_row, * text_ptr1;
183 int r, BitMask, i, bits, width, spacing, letter, underline;
186 unsigned int VideoOffset, VideoOffset1;
190 VideoOffset1 = y * ROWSIZE + x;
194 while (next_row != NULL )
196 text_ptr1 = next_row;
199 if (x==0x8000) { //centered
200 int xx = get_centered_x(text_ptr1);
201 VideoOffset1 = y * ROWSIZE + xx;
204 for (r=0; r<FHEIGHT; r++)
207 text_ptr = text_ptr1;
209 VideoOffset = VideoOffset1;
213 if (*text_ptr == '\n' )
215 next_row = &text_ptr[1];
219 if (*text_ptr == CC_COLOR) {
220 FG_COLOR = *(text_ptr+1);
225 if (*text_ptr == CC_LSPACING) {
226 skip_lines = *(text_ptr+1) - '0';
232 if (*text_ptr == CC_UNDERLINE )
234 if ((r==FBASELINE+2) || (r==FBASELINE+3))
239 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
241 letter = *text_ptr-FMINCHAR;
243 if (!INFONT(letter)) { //not in font, draw as space
244 VideoOffset += spacing;
249 if (FFLAGS & FT_PROPORTIONAL)
252 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
255 for (i=0; i< width; i++ )
256 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
259 fp += BITS_TO_BYTES(width)*r;
263 for (i=0; i< width; i++ )
271 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
273 DATA[VideoOffset++] = (unsigned char) BG_COLOR;
278 VideoOffset += spacing-width; //for kerning
283 VideoOffset1 += ROWSIZE; y++;
287 VideoOffset1 += ROWSIZE * skip_lines;
293 int gr_internal_string0m(int x, int y, char *s )
296 ubyte * text_ptr, * next_row, * text_ptr1;
297 int r, BitMask, i, bits, width, spacing, letter, underline;
300 unsigned int VideoOffset, VideoOffset1;
302 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
306 VideoOffset1 = y * ROWSIZE + x;
310 while (next_row != NULL )
312 text_ptr1 = next_row;
315 if (x==0x8000) { //centered
316 int xx = get_centered_x(text_ptr1);
317 VideoOffset1 = y * ROWSIZE + xx;
320 for (r=0; r<FHEIGHT; r++)
323 text_ptr = text_ptr1;
325 VideoOffset = VideoOffset1;
329 if (*text_ptr == '\n' )
331 next_row = &text_ptr[1];
335 if (*text_ptr == CC_COLOR) {
336 FG_COLOR = *(text_ptr+1);
341 if (*text_ptr == CC_LSPACING) {
342 skip_lines = *(text_ptr+1) - '0';
348 if (*text_ptr == CC_UNDERLINE )
350 if ((r==FBASELINE+2) || (r==FBASELINE+3))
355 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
357 letter = *text_ptr-FMINCHAR;
359 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
360 CHECK_EMBEDDED_COLORS() else{
361 VideoOffset += spacing;
367 if (FFLAGS & FT_PROPORTIONAL)
370 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
373 for (i=0; i< width; i++ )
374 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
377 fp += BITS_TO_BYTES(width)*r;
381 for (i=0; i< width; i++ )
389 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
397 VideoOffset += spacing-width;
400 VideoOffset1 += ROWSIZE;
404 VideoOffset1 += ROWSIZE * skip_lines;
411 int gr_internal_string2(int x, int y, char *s )
414 ubyte * text_ptr, * next_row, * text_ptr1;
415 int r, BitMask, i, bits, width, spacing, letter, underline;
416 int page_switched, skip_lines = 0;
418 unsigned int VideoOffset, VideoOffset1;
420 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
424 gr_vesa_setpage(VideoOffset1 >> 16);
426 VideoOffset1 &= 0xFFFF;
430 while (next_row != NULL )
432 text_ptr1 = next_row;
435 if (x==0x8000) { //centered
436 int xx = get_centered_x(text_ptr1);
437 VideoOffset1 = y * ROWSIZE + xx;
438 gr_vesa_setpage(VideoOffset1 >> 16);
439 VideoOffset1 &= 0xFFFF;
442 for (r=0; r<FHEIGHT; r++)
444 text_ptr = text_ptr1;
446 VideoOffset = VideoOffset1;
452 if (*text_ptr == '\n' )
454 next_row = &text_ptr[1];
458 if (*text_ptr == CC_COLOR) {
459 FG_COLOR = *(text_ptr+1);
464 if (*text_ptr == CC_LSPACING) {
465 skip_lines = *(text_ptr+1) - '0';
471 if (*text_ptr == CC_UNDERLINE )
473 if ((r==FBASELINE+2) || (r==FBASELINE+3))
478 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
480 Assert(width==spacing); //no kerning support here
482 letter = *text_ptr-FMINCHAR;
484 if (!INFONT(letter)) { //not in font, draw as space
485 VideoOffset += spacing;
490 if (FFLAGS & FT_PROPORTIONAL)
493 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
497 if ( VideoOffset+width > 0xFFFF )
499 for (i=0; i< width; i++ )
501 gr_video_memory[VideoOffset++] = FG_COLOR;
503 if (VideoOffset > 0xFFFF )
505 VideoOffset -= 0xFFFF + 1;
513 for (i=0; i< width; i++ )
514 gr_video_memory[VideoOffset++] = FG_COLOR;
523 fp += BITS_TO_BYTES(width)*r;
527 if ( VideoOffset+width > 0xFFFF )
529 for (i=0; i< width; i++ )
537 gr_video_memory[VideoOffset++] = FG_COLOR;
539 gr_video_memory[VideoOffset++] = BG_COLOR;
543 if (VideoOffset > 0xFFFF )
545 VideoOffset -= 0xFFFF + 1;
557 if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR;
558 else gr_video_memory[VideoOffset+0] = BG_COLOR;
560 if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR;
561 else gr_video_memory[VideoOffset+1] = BG_COLOR;
563 if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR;
564 else gr_video_memory[VideoOffset+2] = BG_COLOR;
566 if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR;
567 else gr_video_memory[VideoOffset+3] = BG_COLOR;
569 if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR;
570 else gr_video_memory[VideoOffset+4] = BG_COLOR;
572 if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR;
573 else gr_video_memory[VideoOffset+5] = BG_COLOR;
575 if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR;
576 else gr_video_memory[VideoOffset+6] = BG_COLOR;
578 if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR;
579 else gr_video_memory[VideoOffset+7] = BG_COLOR;
583 for (i=0; i< width/2 ; i++ )
591 gr_video_memory[VideoOffset++] = FG_COLOR;
593 gr_video_memory[VideoOffset++] = BG_COLOR;
605 gr_video_memory[VideoOffset++] = FG_COLOR;
607 gr_video_memory[VideoOffset++] = BG_COLOR;
617 VideoOffset1 += ROWSIZE;
619 if (VideoOffset1 > 0xFFFF ) {
620 VideoOffset1 -= 0xFFFF + 1;
627 VideoOffset1 += ROWSIZE * skip_lines;
633 int gr_internal_string2m(int x, int y, char *s )
636 char * text_ptr, * next_row, * text_ptr1;
637 int r, BitMask, i, bits, width, spacing, letter, underline;
638 int page_switched, skip_lines = 0;
640 unsigned int VideoOffset, VideoOffset1;
642 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
644 gr_vesa_setpage(VideoOffset1 >> 16);
646 VideoOffset1 &= 0xFFFF;
650 while (next_row != NULL )
652 text_ptr1 = next_row;
655 if (x==0x8000) { //centered
656 int xx = get_centered_x(text_ptr1);
657 VideoOffset1 = y * ROWSIZE + xx;
658 gr_vesa_setpage(VideoOffset1 >> 16);
659 VideoOffset1 &= 0xFFFF;
662 for (r=0; r<FHEIGHT; r++)
664 text_ptr = text_ptr1;
666 VideoOffset = VideoOffset1;
672 if (*text_ptr == '\n' )
674 next_row = &text_ptr[1];
678 if (*text_ptr == CC_COLOR) {
679 FG_COLOR = *(text_ptr+1);
684 if (*text_ptr == CC_LSPACING) {
685 skip_lines = *(text_ptr+1) - '0';
691 if (*text_ptr == CC_UNDERLINE )
693 if ((r==FBASELINE+2) || (r==FBASELINE+3))
698 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
700 letter = *text_ptr-FMINCHAR;
702 if (!INFONT(letter)) { //not in font, draw as space
703 VideoOffset += width;
708 if (FFLAGS & FT_PROPORTIONAL)
711 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
715 if ( VideoOffset+width > 0xFFFF )
717 for (i=0; i< width; i++ )
719 gr_video_memory[VideoOffset++] = FG_COLOR;
721 if (VideoOffset > 0xFFFF )
723 VideoOffset -= 0xFFFF + 1;
731 for (i=0; i< width; i++ )
732 gr_video_memory[VideoOffset++] = FG_COLOR;
737 fp += BITS_TO_BYTES(width)*r;
741 if ( VideoOffset+width > 0xFFFF )
743 for (i=0; i< width; i++ )
751 gr_video_memory[VideoOffset++] = FG_COLOR;
757 if (VideoOffset > 0xFFFF )
759 VideoOffset -= 0xFFFF + 1;
766 for (i=0; i< width; i++ )
774 gr_video_memory[VideoOffset++] = FG_COLOR;
783 VideoOffset += spacing-width;
787 VideoOffset1 += ROWSIZE;
789 if (VideoOffset1 > 0xFFFF ) {
790 VideoOffset1 -= 0xFFFF + 1;
797 VideoOffset1 += ROWSIZE * skip_lines;
803 #endif // __ENV_MSDOS__
805 #if defined(POLY_ACC)
806 int gr_internal_string5(int x, int y, char *s )
809 ubyte * text_ptr, * next_row, * text_ptr1;
810 int r, BitMask, i, bits, width, spacing, letter, underline;
813 unsigned int VideoOffset, VideoOffset1;
816 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
820 while (next_row != NULL )
822 text_ptr1 = next_row;
825 if (x==0x8000) { //centered
826 int xx = get_centered_x(text_ptr1);
827 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
830 for (r=0; r<FHEIGHT; r++)
833 text_ptr = text_ptr1;
835 VideoOffset = VideoOffset1;
839 if (*text_ptr == '\n' )
841 next_row = &text_ptr[1];
845 if (*text_ptr == CC_COLOR) {
846 FG_COLOR = *(text_ptr+1);
851 if (*text_ptr == CC_LSPACING) {
852 skip_lines = *(text_ptr+1) - '0';
858 if (*text_ptr == CC_UNDERLINE )
860 if ((r==FBASELINE+2) || (r==FBASELINE+3))
865 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
867 letter = *text_ptr-FMINCHAR;
869 if (!INFONT(letter)) { //not in font, draw as space
870 VideoOffset += spacing * PA_BPP;
875 if (FFLAGS & FT_PROPORTIONAL)
878 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
881 for (i=0; i< width; i++ )
882 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
885 fp += BITS_TO_BYTES(width)*r;
889 for (i=0; i< width; i++ )
897 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
899 { *(short *)(DATA + VideoOffset) = pa_clut[BG_COLOR]; VideoOffset += PA_BPP; }
904 VideoOffset += PA_BPP * (spacing-width); //for kerning
909 VideoOffset1 += ROWSIZE; y++;
913 VideoOffset1 += ROWSIZE * skip_lines;
919 int gr_internal_string5m(int x, int y, char *s )
922 ubyte * text_ptr, * next_row, * text_ptr1;
923 int r, BitMask, i, bits, width, spacing, letter, underline;
926 unsigned int VideoOffset, VideoOffset1;
929 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
933 while (next_row != NULL )
935 text_ptr1 = next_row;
938 if (x==0x8000) { //centered
939 int xx = get_centered_x(text_ptr1);
940 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
943 for (r=0; r<FHEIGHT; r++)
946 text_ptr = text_ptr1;
948 VideoOffset = VideoOffset1;
952 if (*text_ptr == '\n' )
954 next_row = &text_ptr[1];
958 if (*text_ptr == CC_COLOR) {
959 FG_COLOR = *(text_ptr+1);
964 if (*text_ptr == CC_LSPACING) {
965 skip_lines = *(text_ptr+1) - '0';
971 if (*text_ptr == CC_UNDERLINE )
973 if ((r==FBASELINE+2) || (r==FBASELINE+3))
978 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
980 letter = *text_ptr-FMINCHAR;
982 if (!INFONT(letter)) { //not in font, draw as space
983 VideoOffset += spacing * PA_BPP;
988 if (FFLAGS & FT_PROPORTIONAL)
991 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
994 for (i=0; i< width; i++ )
995 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
998 fp += BITS_TO_BYTES(width)*r;
1002 for (i=0; i< width; i++ )
1010 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
1012 VideoOffset += PA_BPP;
1018 VideoOffset += PA_BPP * (spacing-width);
1021 VideoOffset1 += ROWSIZE; y++;
1024 VideoOffset1 += ROWSIZE * skip_lines;
1032 //a bitmap for the character
1033 grs_bitmap char_bm = {
1036 BM_FLAG_TRANSPARENT, //flags
1039 #ifdef BITMAP_SELECTOR
1046 int gr_internal_color_string(int x, int y, char *s )
1049 ubyte * text_ptr, * next_row, * text_ptr1;
1050 int width, spacing,letter;
1053 char_bm.bm_h = FHEIGHT; //set height for chars of this font
1060 while (next_row != NULL)
1062 text_ptr1 = next_row;
1065 text_ptr = text_ptr1;
1069 if (xx==0x8000) //centered
1070 xx = get_centered_x(text_ptr);
1074 if (*text_ptr == '\n' )
1076 next_row = &text_ptr[1];
1081 letter = *text_ptr-FMINCHAR;
1083 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1085 if (!INFONT(letter)) { //not in font, draw as space
1091 if (FFLAGS & FT_PROPORTIONAL)
1092 fp = FCHARS[letter];
1094 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1096 gr_init_bitmap (&char_bm, BM_LINEAR, 0, 0, width, FHEIGHT, width, fp);
1097 gr_bitmapm(xx,yy,&char_bm);
1109 #include "../main/inferno.h"
1110 #include "ogl_init.h"
1112 //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
1114 int pow2ize(int x);//from ogl.c
1116 int get_font_total_width(grs_font * font){
1117 if (font->ft_flags & FT_PROPORTIONAL){
1118 int i,w=0,c=font->ft_minchar;
1119 for (i=0;c<=font->ft_maxchar;i++,c++){
1120 if (font->ft_widths[i]<0)
1122 w+=font->ft_widths[i];
1126 return font->ft_w*(font->ft_maxchar-font->ft_minchar+1);
1129 void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){
1130 int nchars = font->ft_maxchar-font->ft_minchar+1;
1131 int r,x,y,nc=0,smallest=999999,smallr=-1,tries;
1132 int smallprop=10000;
1134 for (h=32;h<=256;h*=2){
1135 // h=pow2ize(font->ft_h*rows+gap*(rows-1));
1136 if (font->ft_h>h)continue;
1137 r=(h/(font->ft_h+gap));
1138 w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r);
1144 mprintf((0,"failed to fit (%ix%i, %ic)\n",w,h,nc));
1149 while(y+font->ft_h<=h){
1154 if (font->ft_flags & FT_PROPORTIONAL){
1155 if (x+font->ft_widths[nc]+gap>w)break;
1156 x+=font->ft_widths[nc++]+gap;
1158 if (x+font->ft_w+gap>w)break;
1172 mprintf((0,"fit: %ix%i %i tries\n",w,h,tries));
1174 if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32)
1195 Error("couldn't fit font?\n");
1196 mprintf((0,"using %ix%i\n",*rw,*rh));
1200 void ogl_init_font(grs_font * font){
1201 int nchars = font->ft_maxchar-font->ft_minchar+1;
1202 int i,w,h,tw,th,x,y,curx=0,cury=0;
1204 // char data[32*32*4];
1206 int gap=0;//having a gap just wastes ram, since we don't filter text textures at all.
1208 ogl_font_choose_size(font,gap,&tw,&th);
1209 data=d_malloc(tw*th);
1210 gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data);
1212 font->ft_parent_bitmap.gltexture=ogl_get_free_texture();
1214 font->ft_bitmaps=(grs_bitmap*)d_malloc( nchars * sizeof(grs_bitmap));
1215 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));
1220 for(i=0;i<nchars;i++){
1221 // s[0]=font->ft_minchar+i;
1222 // gr_get_string_size(s,&w,&h,&aw);
1223 if (font->ft_flags & FT_PROPORTIONAL)
1224 w=font->ft_widths[i];
1227 // mprintf((0,"char %i(%ix%i): ",i,w,h));
1229 mprintf((0,"grr\n"));continue;
1236 Error("font doesn't really fit (%i/%i)?\n",i,nchars);
1237 if (font->ft_flags & FT_COLOR) {
1238 if (font->ft_flags & FT_PROPORTIONAL)
1239 fp = font->ft_chars[i];
1241 fp = font->ft_data + i * w*h;
1244 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w];
1247 // gr_init_bitmap(&font->ft_bitmaps[i],BM_LINEAR,0,0,w,h,w,font->);
1249 int BitMask,bits=0,white=gr_find_closest_color(63,63,63);
1250 // if (w*h>sizeof(data))
1251 // Error("ogl_init_font: toobig\n");
1252 if (font->ft_flags & FT_PROPORTIONAL)
1253 fp = font->ft_chars[i];
1255 fp = font->ft_data + i * BITS_TO_BYTES(w)*h;
1258 for (x=0; x< w; x++ )
1266 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white;
1268 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255;
1273 gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h);
1277 if (!(font->ft_flags & FT_COLOR)) {
1278 //use GL_INTENSITY instead of GL_RGB
1279 if (ogl_intensity4_ok){
1280 font->ft_parent_bitmap.gltexture->internalformat=GL_INTENSITY4;
1281 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE;
1282 }else if (ogl_luminance4_alpha4_ok){
1283 font->ft_parent_bitmap.gltexture->internalformat=GL_LUMINANCE4_ALPHA4;
1284 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE_ALPHA;
1285 }else if (ogl_rgba2_ok){
1286 font->ft_parent_bitmap.gltexture->internalformat=GL_RGBA2;
1287 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1289 font->ft_parent_bitmap.gltexture->internalformat=ogl_rgba_format;
1290 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1293 ogl_loadbmtexture_m(&font->ft_parent_bitmap,0);
1296 int ogl_internal_string(int x, int y, char *s )
1298 ubyte * text_ptr, * next_row, * text_ptr1;
1299 int width, spacing,letter;
1301 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
1307 if (grd_curscreen->sc_canvas.cv_bitmap.bm_type != BM_OGL)
1309 while (next_row != NULL)
1311 text_ptr1 = next_row;
1314 text_ptr = text_ptr1;
1318 if (xx==0x8000) //centered
1319 xx = get_centered_x(text_ptr);
1323 if (*text_ptr == '\n' )
1325 next_row = &text_ptr[1];
1330 letter = *text_ptr-FMINCHAR;
1332 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1334 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
1335 CHECK_EMBEDDED_COLORS() else{
1342 // ogl_ubitblt(FONT->ft_bitmaps[letter].bm_w,FONT->ft_bitmaps[letter].bm_h,xx,yy,0,0,&FONT->ft_bitmaps[letter],NULL);
1343 // if (*text_ptr>='0' && *text_ptr<='9'){
1344 if (FFLAGS&FT_COLOR)
1345 gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);
1347 if (grd_curcanv->cv_bitmap.bm_type==BM_OGL)
1348 ogl_ubitmapm_c(xx,yy,&FONT->ft_bitmaps[letter],FG_COLOR);
1350 Error("ogl_internal_string: non-color string to non-ogl dest\n");
1351 // gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);//ignores color..
1364 int gr_internal_color_string(int x, int y, char *s ){
1365 return ogl_internal_string(x,y,s);
1369 int gr_string(int x, int y, char *s )
1374 Assert(FONT != NULL);
1376 if ( x == 0x8000 ) {
1377 if ( y<0 ) clipped |= 1;
1378 gr_get_string_size(s, &w, &h, &aw );
1379 // for x, since this will be centered, only look at
1381 if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1382 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1384 if ( (y+h) < 0 ) clipped |= 2;
1385 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1388 if ( (x<0) || (y<0) ) clipped |= 1;
1389 gr_get_string_size(s, &w, &h, &aw );
1390 if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1391 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1392 if ( (x+w) < 0 ) clipped |= 2;
1393 if ( (y+h) < 0 ) clipped |= 2;
1394 if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;
1395 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1399 return gr_ustring(x, y, s );
1401 if ( clipped & 2 ) {
1402 // Completely clipped...
1403 mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
1407 if ( clipped & 1 ) {
1408 // Partially clipped...
1409 //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
1412 // Partially clipped...
1415 return ogl_internal_string(x,y,s);
1418 if (FFLAGS & FT_COLOR)
1419 return gr_internal_color_string( x, y, s);
1421 if ( BG_COLOR == -1)
1422 return gr_internal_string_clipped_m( x, y, s );
1424 return gr_internal_string_clipped( x, y, s );
1427 int gr_ustring(int x, int y, char *s )
1431 return ogl_internal_string(x,y,s);
1434 if (FFLAGS & FT_COLOR) {
1436 return gr_internal_color_string(x,y,s);
1443 if ( BG_COLOR == -1)
1444 return gr_internal_string0m(x,y,s);
1446 return gr_internal_string0(x,y,s);
1447 #ifdef __ENV_MSDOS__
1449 if ( BG_COLOR == -1)
1450 return gr_internal_string2m(x,y,s);
1452 return gr_internal_string2(x,y,s);
1453 #endif // __ENV_MSDOS__
1454 #if defined(POLY_ACC)
1456 if ( BG_COLOR == -1)
1457 return gr_internal_string5m(x,y,s);
1459 return gr_internal_string5(x,y,s);
1466 void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width )
1468 int i = 0, longest_width = 0;
1471 *string_height = FHEIGHT;
1473 *average_width = FWIDTH;
1480 // if (*s == CC_UNDERLINE)
1485 *string_height += FHEIGHT;
1491 // 1 = next byte specifies color, so skip the 1 and the color value
1494 else if (*s == CC_LSPACING) {
1495 *string_height += *(s+1)-'0';
1498 get_char_width(s[0],s[1],&width,&spacing);
1500 *string_width += spacing;
1502 if (*string_width > longest_width)
1503 longest_width = *string_width;
1510 *string_width = longest_width;
1514 int gr_uprintf( int x, int y, char * format, ... )
1519 va_start(args, format );
1520 vsprintf(buffer,format,args);
1521 return gr_ustring( x, y, buffer );
1524 int gr_printf( int x, int y, char * format, ... )
1529 va_start(args, format );
1530 vsprintf(buffer,format,args);
1531 return gr_string( x, y, buffer );
1534 void gr_close_font( grs_font * font )
1541 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=font;fontnum++);
1542 Assert(fontnum<MAX_OPEN_FONTS); //did we find slot?
1544 open_font[fontnum].ptr = NULL;
1546 if ( font->ft_chars )
1547 d_free( font->ft_chars );
1548 d_free( font->oldfont );
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);
1560 //remap (by re-reading) all the color fonts
1561 void gr_remap_color_fonts()
1565 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1568 font = open_font[fontnum].ptr;
1570 if (font && (font->ft_flags & FT_COLOR))
1571 gr_remap_font(font,open_font[fontnum].filename);
1575 void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq );
1576 void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count );
1578 #pragma aux decode_data_asm parm [esi] [ecx] [edi] [ebx] modify exact [esi edi eax ebx ecx] = \
1582 "inc dword ptr [ebx+eax*4]" \
1583 "mov al,[edi+eax]" \
1591 grs_font * gr_init_font( char * fontname )
1593 static int first_time=1;
1597 unsigned char * ptr;
1601 int32_t datasize; //size up to (but not including) palette
1605 for (i=0;i<MAX_OPEN_FONTS;i++)
1606 open_font[i].ptr = NULL;
1610 //find free font slot
1611 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=NULL;fontnum++);
1612 Assert(fontnum<MAX_OPEN_FONTS); //did we find one?
1614 strncpy(open_font[fontnum].filename,fontname,FILENAME_LEN);
1616 fontfile = cfopen(fontname, "rb");
1619 Error( "Can't open font file %s", fontname );
1621 cfread(&file_id,sizeof(file_id),1,fontfile);
1622 file_id=swapint(file_id);
1623 cfread(&datasize,sizeof(datasize),1,fontfile);
1624 datasize=swapint(datasize);
1626 if (file_id != 0x4e465350) /* 'NFSP' */
1627 Error( "File %s is not a font file", fontname );
1629 font = (old_grs_font *) d_malloc(datasize);
1630 newfont = (grs_font *) d_malloc(sizeof(grs_font));
1631 newfont->oldfont=font;
1633 open_font[fontnum].ptr = newfont;
1635 cfread(font,1,datasize,fontfile);
1637 newfont->ft_flags=swapint(font->ft_flags);
1638 newfont->ft_w=swapshort(font->ft_w);
1639 newfont->ft_h=swapshort(font->ft_h);
1640 newfont->ft_baseline=swapshort(font->ft_baseline);
1641 newfont->ft_maxchar=font->ft_maxchar;
1642 newfont->ft_minchar=font->ft_minchar;
1643 newfont->ft_bytewidth=swapshort(font->ft_bytewidth);
1645 nchars = newfont->ft_maxchar-newfont->ft_minchar+1;
1647 if (newfont->ft_flags & FT_PROPORTIONAL) {
1649 newfont->ft_widths = (short *) (swapint(font->ft_widths) + ((ubyte *) font));
1650 newfont->ft_data = (swapint(font->ft_data)) + ((ubyte *) font);
1651 newfont->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1653 ptr = newfont->ft_data;
1655 for (i=0; i< nchars; i++ ) {
1656 newfont->ft_chars[i] = ptr;
1657 if (newfont->ft_flags & FT_COLOR)
1658 ptr += newfont->ft_widths[i] * newfont->ft_h;
1660 ptr += BITS_TO_BYTES(newfont->ft_widths[i]) * newfont->ft_h;
1665 newfont->ft_data = ((unsigned char *) font) + sizeof(*font);
1666 newfont->ft_chars = NULL;
1667 newfont->ft_widths = NULL;
1669 ptr = newfont->ft_data + (nchars * newfont->ft_w * newfont->ft_h);
1672 if (newfont->ft_flags & FT_KERNED)
1673 newfont->ft_kerndata = swapint(font->ft_kerndata) + ((ubyte *) font);
1675 if (newfont->ft_flags & FT_COLOR) { //remap palette
1676 ubyte palette[256*3];
1677 ubyte colormap[256];
1680 cfread(palette,3,256,fontfile); //read the palette
1682 #ifdef MACINTOSH // swap the first and last palette entries (black and white)
1687 for (i = 0; i < 3; i++) {
1689 palette[i] = palette[765+i];
1693 // we also need to swap the data entries as well. black is white and white is black
1695 for (i = 0; i < ptr-newfont->ft_data; i++) {
1696 if (newfont->ft_data[i] == 0)
1697 newfont->ft_data[i] = 255;
1698 else if (newfont->ft_data[i] == 255)
1699 newfont->ft_data[i] = 0;
1705 build_colormap_good( (ubyte *)&palette, colormap, freq );
1707 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // chaged from colormap[255] = 255 to this for macintosh
1709 decode_data_asm(newfont->ft_data, ptr-newfont->ft_data, colormap, freq );
1715 // memcpy(newfont,font,(ubyte*)&newfont->oldfont-(ubyte*)newfont);//fill in newfont data from oldfont struct
1716 // mprintf((0,"%i %i %i\n",sizeof(grs_font),sizeof(old_grs_font),(ubyte*)&newfont->oldfont-(ubyte*)newfont));
1726 char tests[]="abcdefghij1234.A";
1727 gr_get_string_size(tests,&x,&y,&aw);
1728 // newfont->ft_aw=x/(float)strlen(tests);
1732 ogl_init_font(newfont);
1739 //remap a font by re-reading its data & palette
1740 void gr_remap_font( grs_font *font, char * fontname )
1746 int32_t datasize; //size up to (but not including) palette
1749 if (! (font->ft_flags & FT_COLOR))
1752 fontfile = cfopen(fontname, "rb");
1755 Error( "Can't open font file %s", fontname );
1757 file_id = cfile_read_int(fontfile);
1758 datasize = cfile_read_int(fontfile);
1760 if (file_id != 0x4e465350) /* 'NFSP' */
1761 Error( "File %s is not a font file", fontname );
1763 nchars = font->ft_maxchar-font->ft_minchar+1;
1765 //compute data length
1767 if (font->ft_flags & FT_PROPORTIONAL) {
1769 for (i=0; i< nchars; i++ ) {
1770 if (font->ft_flags & FT_COLOR)
1771 data_len += font->ft_widths[i] * font->ft_h;
1773 data_len += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1777 data_len = nchars * font->ft_w * font->ft_h;
1779 cfread(font->oldfont, 1, datasize, fontfile); //read raw data
1781 if (font->ft_flags & FT_COLOR) { //remap palette
1782 ubyte palette[256*3];
1783 ubyte colormap[256];
1786 cfseek(fontfile,-sizeof(palette),SEEK_END);
1788 cfread(palette,3,256,fontfile); //read the palette
1790 #ifdef MACINTOSH // swap the first and last palette entries (black and white)
1795 for (i = 0; i < 3; i++) {
1797 palette[i] = palette[765+i];
1801 // we also need to swap the data entries as well. black is white and white is black
1803 for (i = 0; i < data_len; i++) {
1804 if (font->ft_data[i] == 0)
1805 font->ft_data[i] = 255;
1806 else if (font->ft_data[i] == 255)
1807 font->ft_data[i] = 0;
1813 build_colormap_good( (ubyte *)&palette, colormap, freq );
1815 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255;
1817 decode_data_asm(font->ft_data, data_len, colormap, freq );
1825 void gr_set_fontcolor( int fg, int bg )
1831 void gr_set_curfont( grs_font * new )
1837 int gr_internal_string_clipped(int x, int y, char *s )
1840 char * text_ptr, * next_row, * text_ptr1;
1841 int r, BitMask, i, bits, width, spacing, letter, underline;
1848 while (next_row != NULL )
1850 text_ptr1 = next_row;
1854 if (x==0x8000) //centered
1855 x = get_centered_x(text_ptr1);
1859 for (r=0; r<FHEIGHT; r++) {
1860 text_ptr = text_ptr1;
1864 if (*text_ptr == '\n' ) {
1865 next_row = &text_ptr[1];
1869 if (*text_ptr == CC_COLOR) {
1870 FG_COLOR = *(text_ptr+1);
1875 if (*text_ptr == CC_LSPACING) {
1876 Int3(); // Warning: skip lines not supported for clipped strings.
1882 if (*text_ptr == CC_UNDERLINE ) {
1883 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1888 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1890 letter = *text_ptr-FMINCHAR;
1892 if (!INFONT(letter)) { //not in font, draw as space
1898 if (FFLAGS & FT_PROPORTIONAL)
1899 fp = FCHARS[letter];
1901 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1904 for (i=0; i< width; i++ ) {
1905 gr_setcolor(FG_COLOR);
1909 fp += BITS_TO_BYTES(width)*r;
1913 for (i=0; i< width; i++ ) {
1919 gr_setcolor(FG_COLOR);
1921 gr_setcolor(BG_COLOR);
1927 x += spacing-width; //for kerning
1937 int gr_internal_string_clipped_m(int x, int y, char *s )
1940 char * text_ptr, * next_row, * text_ptr1;
1941 int r, BitMask, i, bits, width, spacing, letter, underline;
1948 while (next_row != NULL )
1950 text_ptr1 = next_row;
1954 if (x==0x8000) //centered
1955 x = get_centered_x(text_ptr1);
1959 for (r=0; r<FHEIGHT; r++) {
1962 text_ptr = text_ptr1;
1965 if (*text_ptr == '\n' ) {
1966 next_row = &text_ptr[1];
1970 if (*text_ptr == CC_COLOR) {
1971 FG_COLOR = *(text_ptr+1);
1976 if (*text_ptr == CC_LSPACING) {
1977 Int3(); // Warning: skip lines not supported for clipped strings.
1983 if (*text_ptr == CC_UNDERLINE ) {
1984 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1989 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1991 letter = *text_ptr-FMINCHAR;
1993 if (!INFONT(letter)) { //not in font, draw as space
1999 if (FFLAGS & FT_PROPORTIONAL)
2000 fp = FCHARS[letter];
2002 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
2005 for (i=0; i< width; i++ ) {
2006 gr_setcolor(FG_COLOR);
2010 fp += BITS_TO_BYTES(width)*r;
2014 for (i=0; i< width; i++ ) {
2019 if (bits & BitMask) {
2020 gr_setcolor(FG_COLOR);
2029 x += spacing-width; //for kerning