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-08 10:37:25 $
19 * Graphical routines for drawing fonts.
21 * $Log: not supported by cvs2svn $
22 * Revision 1.8 2001/11/04 03:58:25 bradleyb
23 * re-init ogl fonts after remapping colors.
25 * Revision 1.7 2001/11/02 10:46:23 bradleyb
26 * fixed gr_remap_font, minor stuff
28 * Revision 1.6 2001/11/02 02:03:35 bradleyb
29 * Enable OpenGL fonts\!
46 #include "pa_enabl.h" //$$POLY_ACC
62 #define MAX_OPEN_FONTS 50
63 #define FILENAME_LEN 13
65 typedef struct openfont {
66 char filename[FILENAME_LEN];
70 //list of open fonts, for use (for now) for palette remapping
71 openfont open_font[MAX_OPEN_FONTS];
73 #define FONT grd_curcanv->cv_font
74 #define FG_COLOR grd_curcanv->cv_font_fg_color
75 #define BG_COLOR grd_curcanv->cv_font_bg_color
76 #define FWIDTH FONT->ft_w
77 #define FHEIGHT FONT->ft_h
78 #define FBASELINE FONT->ft_baseline
79 #define FFLAGS FONT->ft_flags
80 #define FMINCHAR FONT->ft_minchar
81 #define FMAXCHAR FONT->ft_maxchar
82 #define FDATA FONT->ft_data
83 #define FCHARS FONT->ft_chars
84 #define FWIDTHS FONT->ft_widths
86 #define BITS_TO_BYTES(x) (((x)+7)>>3)
88 int gr_internal_string_clipped(int x, int y, char *s );
89 int gr_internal_string_clipped_m(int x, int y, char *s );
91 ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second)
93 ubyte *p=font->ft_kerndata;
96 if (p[0]==first && p[1]==second)
104 //takes the character AFTER being offset into font
105 #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
107 //takes the character BEFORE being offset into current font
108 void get_char_width(ubyte c,ubyte c2,int *width,int *spacing)
114 if (!INFONT(letter)) { //not in font, draw as space
116 if (FFLAGS & FT_PROPORTIONAL)
123 if (FFLAGS & FT_PROPORTIONAL)
124 *width = FWIDTHS[letter];
130 if (FFLAGS & FT_KERNED) {
133 if (!(c2==0 || c2=='\n')) {
136 letter2 = c2-FMINCHAR;
138 if (INFONT(letter2)) {
140 p = find_kern_entry(FONT,(ubyte)letter,letter2);
149 int get_centered_x(char *s)
153 for (w=0;*s!=0 && *s!='\n';s++) {
157 continue;//skip color codes.
159 get_char_width(s[0],s[1],&w2,&s2);
163 return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
166 //hack to allow color codes to be embedded in strings -MPM
167 //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string.
168 //function must already have orig_color var set (or they could be passed as args...)
169 //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain
170 int gr_message_color_level=1;
171 #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x03)) { \
174 if (gr_message_color_level >= *(text_ptr-1)) \
175 FG_COLOR = *text_ptr - 1; \
179 else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \
180 if (gr_message_color_level >= *text_ptr - 3) \
181 FG_COLOR=orig_color; \
185 int gr_internal_string0(int x, int y, char *s )
188 ubyte * text_ptr, * next_row, * text_ptr1;
189 int r, BitMask, i, bits, width, spacing, letter, underline;
192 unsigned int VideoOffset, VideoOffset1;
196 VideoOffset1 = y * ROWSIZE + x;
200 while (next_row != NULL )
202 text_ptr1 = next_row;
205 if (x==0x8000) { //centered
206 int xx = get_centered_x(text_ptr1);
207 VideoOffset1 = y * ROWSIZE + xx;
210 for (r=0; r<FHEIGHT; r++)
213 text_ptr = text_ptr1;
215 VideoOffset = VideoOffset1;
219 if (*text_ptr == '\n' )
221 next_row = &text_ptr[1];
225 if (*text_ptr == CC_COLOR) {
226 FG_COLOR = *(text_ptr+1);
231 if (*text_ptr == CC_LSPACING) {
232 skip_lines = *(text_ptr+1) - '0';
238 if (*text_ptr == CC_UNDERLINE )
240 if ((r==FBASELINE+2) || (r==FBASELINE+3))
245 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
247 letter = *text_ptr-FMINCHAR;
249 if (!INFONT(letter)) { //not in font, draw as space
250 VideoOffset += spacing;
255 if (FFLAGS & FT_PROPORTIONAL)
258 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
261 for (i=0; i< width; i++ )
262 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
265 fp += BITS_TO_BYTES(width)*r;
269 for (i=0; i< width; i++ )
277 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
279 DATA[VideoOffset++] = (unsigned char) BG_COLOR;
284 VideoOffset += spacing-width; //for kerning
289 VideoOffset1 += ROWSIZE; y++;
293 VideoOffset1 += ROWSIZE * skip_lines;
299 int gr_internal_string0m(int x, int y, char *s )
302 ubyte * text_ptr, * next_row, * text_ptr1;
303 int r, BitMask, i, bits, width, spacing, letter, underline;
306 unsigned int VideoOffset, VideoOffset1;
308 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
312 VideoOffset1 = y * ROWSIZE + x;
316 while (next_row != NULL )
318 text_ptr1 = next_row;
321 if (x==0x8000) { //centered
322 int xx = get_centered_x(text_ptr1);
323 VideoOffset1 = y * ROWSIZE + xx;
326 for (r=0; r<FHEIGHT; r++)
329 text_ptr = text_ptr1;
331 VideoOffset = VideoOffset1;
335 if (*text_ptr == '\n' )
337 next_row = &text_ptr[1];
341 if (*text_ptr == CC_COLOR) {
342 FG_COLOR = *(text_ptr+1);
347 if (*text_ptr == CC_LSPACING) {
348 skip_lines = *(text_ptr+1) - '0';
354 if (*text_ptr == CC_UNDERLINE )
356 if ((r==FBASELINE+2) || (r==FBASELINE+3))
361 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
363 letter = *text_ptr-FMINCHAR;
365 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
366 CHECK_EMBEDDED_COLORS() else{
367 VideoOffset += spacing;
373 if (FFLAGS & FT_PROPORTIONAL)
376 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
379 for (i=0; i< width; i++ )
380 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
383 fp += BITS_TO_BYTES(width)*r;
387 for (i=0; i< width; i++ )
395 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
403 VideoOffset += spacing-width;
406 VideoOffset1 += ROWSIZE;
410 VideoOffset1 += ROWSIZE * skip_lines;
417 int gr_internal_string2(int x, int y, char *s )
420 ubyte * text_ptr, * next_row, * text_ptr1;
421 int r, BitMask, i, bits, width, spacing, letter, underline;
422 int page_switched, skip_lines = 0;
424 unsigned int VideoOffset, VideoOffset1;
426 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
430 gr_vesa_setpage(VideoOffset1 >> 16);
432 VideoOffset1 &= 0xFFFF;
436 while (next_row != NULL )
438 text_ptr1 = next_row;
441 if (x==0x8000) { //centered
442 int xx = get_centered_x(text_ptr1);
443 VideoOffset1 = y * ROWSIZE + xx;
444 gr_vesa_setpage(VideoOffset1 >> 16);
445 VideoOffset1 &= 0xFFFF;
448 for (r=0; r<FHEIGHT; r++)
450 text_ptr = text_ptr1;
452 VideoOffset = VideoOffset1;
458 if (*text_ptr == '\n' )
460 next_row = &text_ptr[1];
464 if (*text_ptr == CC_COLOR) {
465 FG_COLOR = *(text_ptr+1);
470 if (*text_ptr == CC_LSPACING) {
471 skip_lines = *(text_ptr+1) - '0';
477 if (*text_ptr == CC_UNDERLINE )
479 if ((r==FBASELINE+2) || (r==FBASELINE+3))
484 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
486 Assert(width==spacing); //no kerning support here
488 letter = *text_ptr-FMINCHAR;
490 if (!INFONT(letter)) { //not in font, draw as space
491 VideoOffset += spacing;
496 if (FFLAGS & FT_PROPORTIONAL)
499 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
503 if ( VideoOffset+width > 0xFFFF )
505 for (i=0; i< width; i++ )
507 gr_video_memory[VideoOffset++] = FG_COLOR;
509 if (VideoOffset > 0xFFFF )
511 VideoOffset -= 0xFFFF + 1;
519 for (i=0; i< width; i++ )
520 gr_video_memory[VideoOffset++] = FG_COLOR;
529 fp += BITS_TO_BYTES(width)*r;
533 if ( VideoOffset+width > 0xFFFF )
535 for (i=0; i< width; i++ )
543 gr_video_memory[VideoOffset++] = FG_COLOR;
545 gr_video_memory[VideoOffset++] = BG_COLOR;
549 if (VideoOffset > 0xFFFF )
551 VideoOffset -= 0xFFFF + 1;
563 if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR;
564 else gr_video_memory[VideoOffset+0] = BG_COLOR;
566 if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR;
567 else gr_video_memory[VideoOffset+1] = BG_COLOR;
569 if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR;
570 else gr_video_memory[VideoOffset+2] = BG_COLOR;
572 if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR;
573 else gr_video_memory[VideoOffset+3] = BG_COLOR;
575 if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR;
576 else gr_video_memory[VideoOffset+4] = BG_COLOR;
578 if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR;
579 else gr_video_memory[VideoOffset+5] = BG_COLOR;
581 if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR;
582 else gr_video_memory[VideoOffset+6] = BG_COLOR;
584 if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR;
585 else gr_video_memory[VideoOffset+7] = BG_COLOR;
589 for (i=0; i< width/2 ; i++ )
597 gr_video_memory[VideoOffset++] = FG_COLOR;
599 gr_video_memory[VideoOffset++] = BG_COLOR;
611 gr_video_memory[VideoOffset++] = FG_COLOR;
613 gr_video_memory[VideoOffset++] = BG_COLOR;
623 VideoOffset1 += ROWSIZE;
625 if (VideoOffset1 > 0xFFFF ) {
626 VideoOffset1 -= 0xFFFF + 1;
633 VideoOffset1 += ROWSIZE * skip_lines;
639 int gr_internal_string2m(int x, int y, char *s )
642 char * text_ptr, * next_row, * text_ptr1;
643 int r, BitMask, i, bits, width, spacing, letter, underline;
644 int page_switched, skip_lines = 0;
646 unsigned int VideoOffset, VideoOffset1;
648 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
650 gr_vesa_setpage(VideoOffset1 >> 16);
652 VideoOffset1 &= 0xFFFF;
656 while (next_row != NULL )
658 text_ptr1 = next_row;
661 if (x==0x8000) { //centered
662 int xx = get_centered_x(text_ptr1);
663 VideoOffset1 = y * ROWSIZE + xx;
664 gr_vesa_setpage(VideoOffset1 >> 16);
665 VideoOffset1 &= 0xFFFF;
668 for (r=0; r<FHEIGHT; r++)
670 text_ptr = text_ptr1;
672 VideoOffset = VideoOffset1;
678 if (*text_ptr == '\n' )
680 next_row = &text_ptr[1];
684 if (*text_ptr == CC_COLOR) {
685 FG_COLOR = *(text_ptr+1);
690 if (*text_ptr == CC_LSPACING) {
691 skip_lines = *(text_ptr+1) - '0';
697 if (*text_ptr == CC_UNDERLINE )
699 if ((r==FBASELINE+2) || (r==FBASELINE+3))
704 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
706 letter = *text_ptr-FMINCHAR;
708 if (!INFONT(letter)) { //not in font, draw as space
709 VideoOffset += width;
714 if (FFLAGS & FT_PROPORTIONAL)
717 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
721 if ( VideoOffset+width > 0xFFFF )
723 for (i=0; i< width; i++ )
725 gr_video_memory[VideoOffset++] = FG_COLOR;
727 if (VideoOffset > 0xFFFF )
729 VideoOffset -= 0xFFFF + 1;
737 for (i=0; i< width; i++ )
738 gr_video_memory[VideoOffset++] = FG_COLOR;
743 fp += BITS_TO_BYTES(width)*r;
747 if ( VideoOffset+width > 0xFFFF )
749 for (i=0; i< width; i++ )
757 gr_video_memory[VideoOffset++] = FG_COLOR;
763 if (VideoOffset > 0xFFFF )
765 VideoOffset -= 0xFFFF + 1;
772 for (i=0; i< width; i++ )
780 gr_video_memory[VideoOffset++] = FG_COLOR;
789 VideoOffset += spacing-width;
793 VideoOffset1 += ROWSIZE;
795 if (VideoOffset1 > 0xFFFF ) {
796 VideoOffset1 -= 0xFFFF + 1;
803 VideoOffset1 += ROWSIZE * skip_lines;
809 #endif // __ENV_MSDOS__
811 #if defined(POLY_ACC)
812 int gr_internal_string5(int x, int y, char *s )
815 ubyte * text_ptr, * next_row, * text_ptr1;
816 int r, BitMask, i, bits, width, spacing, letter, underline;
819 unsigned int VideoOffset, VideoOffset1;
822 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
826 while (next_row != NULL )
828 text_ptr1 = next_row;
831 if (x==0x8000) { //centered
832 int xx = get_centered_x(text_ptr1);
833 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
836 for (r=0; r<FHEIGHT; r++)
839 text_ptr = text_ptr1;
841 VideoOffset = VideoOffset1;
845 if (*text_ptr == '\n' )
847 next_row = &text_ptr[1];
851 if (*text_ptr == CC_COLOR) {
852 FG_COLOR = *(text_ptr+1);
857 if (*text_ptr == CC_LSPACING) {
858 skip_lines = *(text_ptr+1) - '0';
864 if (*text_ptr == CC_UNDERLINE )
866 if ((r==FBASELINE+2) || (r==FBASELINE+3))
871 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
873 letter = *text_ptr-FMINCHAR;
875 if (!INFONT(letter)) { //not in font, draw as space
876 VideoOffset += spacing * PA_BPP;
881 if (FFLAGS & FT_PROPORTIONAL)
884 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
887 for (i=0; i< width; i++ )
888 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
891 fp += BITS_TO_BYTES(width)*r;
895 for (i=0; i< width; i++ )
903 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
905 { *(short *)(DATA + VideoOffset) = pa_clut[BG_COLOR]; VideoOffset += PA_BPP; }
910 VideoOffset += PA_BPP * (spacing-width); //for kerning
915 VideoOffset1 += ROWSIZE; y++;
919 VideoOffset1 += ROWSIZE * skip_lines;
925 int gr_internal_string5m(int x, int y, char *s )
928 ubyte * text_ptr, * next_row, * text_ptr1;
929 int r, BitMask, i, bits, width, spacing, letter, underline;
932 unsigned int VideoOffset, VideoOffset1;
935 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
939 while (next_row != NULL )
941 text_ptr1 = next_row;
944 if (x==0x8000) { //centered
945 int xx = get_centered_x(text_ptr1);
946 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
949 for (r=0; r<FHEIGHT; r++)
952 text_ptr = text_ptr1;
954 VideoOffset = VideoOffset1;
958 if (*text_ptr == '\n' )
960 next_row = &text_ptr[1];
964 if (*text_ptr == CC_COLOR) {
965 FG_COLOR = *(text_ptr+1);
970 if (*text_ptr == CC_LSPACING) {
971 skip_lines = *(text_ptr+1) - '0';
977 if (*text_ptr == CC_UNDERLINE )
979 if ((r==FBASELINE+2) || (r==FBASELINE+3))
984 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
986 letter = *text_ptr-FMINCHAR;
988 if (!INFONT(letter)) { //not in font, draw as space
989 VideoOffset += spacing * PA_BPP;
994 if (FFLAGS & FT_PROPORTIONAL)
997 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1000 for (i=0; i< width; i++ )
1001 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
1004 fp += BITS_TO_BYTES(width)*r;
1008 for (i=0; i< width; i++ )
1016 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
1018 VideoOffset += PA_BPP;
1024 VideoOffset += PA_BPP * (spacing-width);
1027 VideoOffset1 += ROWSIZE; y++;
1030 VideoOffset1 += ROWSIZE * skip_lines;
1038 //a bitmap for the character
1039 grs_bitmap char_bm = {
1042 BM_FLAG_TRANSPARENT, //flags
1045 #ifdef BITMAP_SELECTOR
1052 int gr_internal_color_string(int x, int y, char *s )
1055 ubyte * text_ptr, * next_row, * text_ptr1;
1056 int width, spacing,letter;
1059 char_bm.bm_h = FHEIGHT; //set height for chars of this font
1066 while (next_row != NULL)
1068 text_ptr1 = next_row;
1071 text_ptr = text_ptr1;
1075 if (xx==0x8000) //centered
1076 xx = get_centered_x(text_ptr);
1080 if (*text_ptr == '\n' )
1082 next_row = &text_ptr[1];
1087 letter = *text_ptr-FMINCHAR;
1089 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1091 if (!INFONT(letter)) { //not in font, draw as space
1097 if (FFLAGS & FT_PROPORTIONAL)
1098 fp = FCHARS[letter];
1100 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1102 gr_init_bitmap (&char_bm, BM_LINEAR, 0, 0, width, FHEIGHT, width, fp);
1103 gr_bitmapm(xx,yy,&char_bm);
1115 #include "../main/inferno.h"
1116 #include "ogl_init.h"
1118 //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
1120 int pow2ize(int x);//from ogl.c
1122 int get_font_total_width(grs_font * font){
1123 if (font->ft_flags & FT_PROPORTIONAL){
1124 int i,w=0,c=font->ft_minchar;
1125 for (i=0;c<=font->ft_maxchar;i++,c++){
1126 if (font->ft_widths[i]<0)
1128 w+=font->ft_widths[i];
1132 return font->ft_w*(font->ft_maxchar-font->ft_minchar+1);
1135 void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){
1136 int nchars = font->ft_maxchar-font->ft_minchar+1;
1137 int r,x,y,nc=0,smallest=999999,smallr=-1,tries;
1138 int smallprop=10000;
1140 for (h=32;h<=256;h*=2){
1141 // h=pow2ize(font->ft_h*rows+gap*(rows-1));
1142 if (font->ft_h>h)continue;
1143 r=(h/(font->ft_h+gap));
1144 w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r);
1150 mprintf((0,"failed to fit (%ix%i, %ic)\n",w,h,nc));
1155 while(y+font->ft_h<=h){
1160 if (font->ft_flags & FT_PROPORTIONAL){
1161 if (x+font->ft_widths[nc]+gap>w)break;
1162 x+=font->ft_widths[nc++]+gap;
1164 if (x+font->ft_w+gap>w)break;
1178 mprintf((0,"fit: %ix%i %i tries\n",w,h,tries));
1180 if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32)
1201 Error("couldn't fit font?\n");
1202 mprintf((0,"using %ix%i\n",*rw,*rh));
1206 void ogl_init_font(grs_font * font){
1207 int nchars = font->ft_maxchar-font->ft_minchar+1;
1208 int i,w,h,tw,th,x,y,curx=0,cury=0;
1210 // char data[32*32*4];
1212 int gap=0;//having a gap just wastes ram, since we don't filter text textures at all.
1214 ogl_font_choose_size(font,gap,&tw,&th);
1215 data=d_malloc(tw*th);
1216 gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data);
1218 font->ft_parent_bitmap.gltexture=ogl_get_free_texture();
1220 font->ft_bitmaps=(grs_bitmap*)d_malloc( nchars * sizeof(grs_bitmap));
1221 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));
1226 for(i=0;i<nchars;i++){
1227 // s[0]=font->ft_minchar+i;
1228 // gr_get_string_size(s,&w,&h,&aw);
1229 if (font->ft_flags & FT_PROPORTIONAL)
1230 w=font->ft_widths[i];
1233 // mprintf((0,"char %i(%ix%i): ",i,w,h));
1235 mprintf((0,"grr\n"));continue;
1242 Error("font doesn't really fit (%i/%i)?\n",i,nchars);
1243 if (font->ft_flags & FT_COLOR) {
1244 if (font->ft_flags & FT_PROPORTIONAL)
1245 fp = font->ft_chars[i];
1247 fp = font->ft_data + i * w*h;
1250 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w];
1253 // gr_init_bitmap(&font->ft_bitmaps[i],BM_LINEAR,0,0,w,h,w,font->);
1255 int BitMask,bits=0,white=gr_find_closest_color(63,63,63);
1256 // if (w*h>sizeof(data))
1257 // Error("ogl_init_font: toobig\n");
1258 if (font->ft_flags & FT_PROPORTIONAL)
1259 fp = font->ft_chars[i];
1261 fp = font->ft_data + i * BITS_TO_BYTES(w)*h;
1264 for (x=0; x< w; x++ )
1272 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white;
1274 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255;
1279 gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h);
1283 if (!(font->ft_flags & FT_COLOR)) {
1284 //use GL_INTENSITY instead of GL_RGB
1285 if (ogl_intensity4_ok){
1286 font->ft_parent_bitmap.gltexture->internalformat=GL_INTENSITY4;
1287 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE;
1288 }else if (ogl_luminance4_alpha4_ok){
1289 font->ft_parent_bitmap.gltexture->internalformat=GL_LUMINANCE4_ALPHA4;
1290 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE_ALPHA;
1291 }else if (ogl_rgba2_ok){
1292 font->ft_parent_bitmap.gltexture->internalformat=GL_RGBA2;
1293 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1295 font->ft_parent_bitmap.gltexture->internalformat=ogl_rgba_format;
1296 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1299 ogl_loadbmtexture_m(&font->ft_parent_bitmap,0);
1302 int ogl_internal_string(int x, int y, char *s )
1304 ubyte * text_ptr, * next_row, * text_ptr1;
1305 int width, spacing,letter;
1307 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
1313 if (grd_curscreen->sc_canvas.cv_bitmap.bm_type != BM_OGL)
1315 while (next_row != NULL)
1317 text_ptr1 = next_row;
1320 text_ptr = text_ptr1;
1324 if (xx==0x8000) //centered
1325 xx = get_centered_x(text_ptr);
1329 if (*text_ptr == '\n' )
1331 next_row = &text_ptr[1];
1336 letter = *text_ptr-FMINCHAR;
1338 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1340 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
1341 CHECK_EMBEDDED_COLORS() else{
1348 // ogl_ubitblt(FONT->ft_bitmaps[letter].bm_w,FONT->ft_bitmaps[letter].bm_h,xx,yy,0,0,&FONT->ft_bitmaps[letter],NULL);
1349 // if (*text_ptr>='0' && *text_ptr<='9'){
1350 if (FFLAGS&FT_COLOR)
1351 gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);
1353 if (grd_curcanv->cv_bitmap.bm_type==BM_OGL)
1354 ogl_ubitmapm_c(xx,yy,&FONT->ft_bitmaps[letter],FG_COLOR);
1356 Error("ogl_internal_string: non-color string to non-ogl dest\n");
1357 // gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);//ignores color..
1370 int gr_internal_color_string(int x, int y, char *s ){
1371 return ogl_internal_string(x,y,s);
1375 int gr_string(int x, int y, char *s )
1380 Assert(FONT != NULL);
1382 if ( x == 0x8000 ) {
1383 if ( y<0 ) clipped |= 1;
1384 gr_get_string_size(s, &w, &h, &aw );
1385 // for x, since this will be centered, only look at
1387 if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1388 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1390 if ( (y+h) < 0 ) clipped |= 2;
1391 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1394 if ( (x<0) || (y<0) ) clipped |= 1;
1395 gr_get_string_size(s, &w, &h, &aw );
1396 if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1397 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1398 if ( (x+w) < 0 ) clipped |= 2;
1399 if ( (y+h) < 0 ) clipped |= 2;
1400 if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;
1401 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1405 return gr_ustring(x, y, s );
1407 if ( clipped & 2 ) {
1408 // Completely clipped...
1409 mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
1413 if ( clipped & 1 ) {
1414 // Partially clipped...
1415 //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
1418 // Partially clipped...
1421 return ogl_internal_string(x,y,s);
1424 if (FFLAGS & FT_COLOR)
1425 return gr_internal_color_string( x, y, s);
1427 if ( BG_COLOR == -1)
1428 return gr_internal_string_clipped_m( x, y, s );
1430 return gr_internal_string_clipped( x, y, s );
1433 int gr_ustring(int x, int y, char *s )
1437 return ogl_internal_string(x,y,s);
1440 if (FFLAGS & FT_COLOR) {
1442 return gr_internal_color_string(x,y,s);
1449 if ( BG_COLOR == -1)
1450 return gr_internal_string0m(x,y,s);
1452 return gr_internal_string0(x,y,s);
1453 #ifdef __ENV_MSDOS__
1455 if ( BG_COLOR == -1)
1456 return gr_internal_string2m(x,y,s);
1458 return gr_internal_string2(x,y,s);
1459 #endif // __ENV_MSDOS__
1460 #if defined(POLY_ACC)
1462 if ( BG_COLOR == -1)
1463 return gr_internal_string5m(x,y,s);
1465 return gr_internal_string5(x,y,s);
1472 void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width )
1474 int i = 0, longest_width = 0;
1477 *string_height = FHEIGHT;
1479 *average_width = FWIDTH;
1486 // if (*s == CC_UNDERLINE)
1491 *string_height += FHEIGHT;
1497 // 1 = next byte specifies color, so skip the 1 and the color value
1500 else if (*s == CC_LSPACING) {
1501 *string_height += *(s+1)-'0';
1504 get_char_width(s[0],s[1],&width,&spacing);
1506 *string_width += spacing;
1508 if (*string_width > longest_width)
1509 longest_width = *string_width;
1516 *string_width = longest_width;
1520 int gr_uprintf( int x, int y, char * format, ... )
1525 va_start(args, format );
1526 vsprintf(buffer,format,args);
1527 return gr_ustring( x, y, buffer );
1530 int gr_printf( int x, int y, char * format, ... )
1535 va_start(args, format );
1536 vsprintf(buffer,format,args);
1537 return gr_string( x, y, buffer );
1540 void gr_close_font( grs_font * font )
1547 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=font;fontnum++);
1548 Assert(fontnum<MAX_OPEN_FONTS); //did we find slot?
1550 open_font[fontnum].ptr = NULL;
1552 if ( font->ft_chars )
1553 d_free( font->ft_chars );
1554 d_free( font->oldfont );
1556 if (font->ft_bitmaps)
1557 d_free( font->ft_bitmaps );
1558 gr_free_bitmap_data(&font->ft_parent_bitmap);
1559 // ogl_freebmtexture(&font->ft_parent_bitmap);
1566 //remap (by re-reading) all the color fonts
1567 void gr_remap_color_fonts()
1571 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1574 font = open_font[fontnum].ptr;
1576 if (font && (font->ft_flags & FT_COLOR))
1577 gr_remap_font(font,open_font[fontnum].filename);
1581 void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq );
1582 void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count );
1584 #pragma aux decode_data_asm parm [esi] [ecx] [edi] [ebx] modify exact [esi edi eax ebx ecx] = \
1588 "inc dword ptr [ebx+eax*4]" \
1589 "mov al,[edi+eax]" \
1597 grs_font * gr_init_font( char * fontname )
1599 static int first_time=1;
1603 unsigned char * ptr;
1607 int32_t datasize; //size up to (but not including) palette
1611 for (i=0;i<MAX_OPEN_FONTS;i++)
1612 open_font[i].ptr = NULL;
1616 //find free font slot
1617 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=NULL;fontnum++);
1618 Assert(fontnum<MAX_OPEN_FONTS); //did we find one?
1620 strncpy(open_font[fontnum].filename,fontname,FILENAME_LEN);
1622 fontfile = cfopen(fontname, "rb");
1625 Error( "Can't open font file %s", fontname );
1627 cfread(&file_id,sizeof(file_id),1,fontfile);
1628 file_id=swapint(file_id);
1629 cfread(&datasize,sizeof(datasize),1,fontfile);
1630 datasize=swapint(datasize);
1632 if (file_id != 0x4e465350) /* 'NFSP' */
1633 Error( "File %s is not a font file", fontname );
1635 font = (old_grs_font *) d_malloc(datasize);
1636 newfont = (grs_font *) d_malloc(sizeof(grs_font));
1637 newfont->oldfont=font;
1639 open_font[fontnum].ptr = newfont;
1641 cfread(font,1,datasize,fontfile);
1643 newfont->ft_flags=swapint(font->ft_flags);
1644 newfont->ft_w=swapshort(font->ft_w);
1645 newfont->ft_h=swapshort(font->ft_h);
1646 newfont->ft_baseline=swapshort(font->ft_baseline);
1647 newfont->ft_maxchar=font->ft_maxchar;
1648 newfont->ft_minchar=font->ft_minchar;
1649 newfont->ft_bytewidth=swapshort(font->ft_bytewidth);
1651 nchars = newfont->ft_maxchar-newfont->ft_minchar+1;
1653 if (newfont->ft_flags & FT_PROPORTIONAL) {
1655 newfont->ft_widths = (short *) (swapint(font->ft_widths) + ((ubyte *) font));
1656 newfont->ft_data = (swapint(font->ft_data)) + ((ubyte *) font);
1657 newfont->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1659 ptr = newfont->ft_data;
1661 for (i=0; i< nchars; i++ ) {
1662 newfont->ft_chars[i] = ptr;
1663 if (newfont->ft_flags & FT_COLOR)
1664 ptr += newfont->ft_widths[i] * newfont->ft_h;
1666 ptr += BITS_TO_BYTES(newfont->ft_widths[i]) * newfont->ft_h;
1671 newfont->ft_data = ((unsigned char *) font) + sizeof(*font);
1672 newfont->ft_chars = NULL;
1673 newfont->ft_widths = NULL;
1675 ptr = newfont->ft_data + (nchars * newfont->ft_w * newfont->ft_h);
1678 if (newfont->ft_flags & FT_KERNED)
1679 newfont->ft_kerndata = swapint(font->ft_kerndata) + ((ubyte *) font);
1681 if (newfont->ft_flags & FT_COLOR) { //remap palette
1682 ubyte palette[256*3];
1683 ubyte colormap[256];
1686 cfread(palette,3,256,fontfile); //read the palette
1688 #ifdef MACINTOSH // swap the first and last palette entries (black and white)
1693 for (i = 0; i < 3; i++) {
1695 palette[i] = palette[765+i];
1699 // we also need to swap the data entries as well. black is white and white is black
1701 for (i = 0; i < ptr-newfont->ft_data; i++) {
1702 if (newfont->ft_data[i] == 0)
1703 newfont->ft_data[i] = 255;
1704 else if (newfont->ft_data[i] == 255)
1705 newfont->ft_data[i] = 0;
1711 build_colormap_good( (ubyte *)&palette, colormap, freq );
1713 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // chaged from colormap[255] = 255 to this for macintosh
1715 decode_data_asm(newfont->ft_data, ptr-newfont->ft_data, colormap, freq );
1721 // memcpy(newfont,font,(ubyte*)&newfont->oldfont-(ubyte*)newfont);//fill in newfont data from oldfont struct
1722 // mprintf((0,"%i %i %i\n",sizeof(grs_font),sizeof(old_grs_font),(ubyte*)&newfont->oldfont-(ubyte*)newfont));
1732 char tests[]="abcdefghij1234.A";
1733 gr_get_string_size(tests,&x,&y,&aw);
1734 // newfont->ft_aw=x/(float)strlen(tests);
1738 ogl_init_font(newfont);
1745 //remap a font by re-reading its data & palette
1746 void gr_remap_font( grs_font *font, char * fontname )
1752 int32_t datasize; //size up to (but not including) palette
1755 if (! (font->ft_flags & FT_COLOR))
1758 fontfile = cfopen(fontname, "rb");
1761 Error( "Can't open font file %s", fontname );
1763 file_id = cfile_read_int(fontfile);
1764 datasize = cfile_read_int(fontfile);
1766 if (file_id != 0x4e465350) /* 'NFSP' */
1767 Error( "File %s is not a font file", fontname );
1769 nchars = font->ft_maxchar-font->ft_minchar+1;
1771 //compute data length
1773 if (font->ft_flags & FT_PROPORTIONAL) {
1775 for (i=0; i< nchars; i++ ) {
1776 if (font->ft_flags & FT_COLOR)
1777 data_len += font->ft_widths[i] * font->ft_h;
1779 data_len += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1783 data_len = nchars * font->ft_w * font->ft_h;
1785 cfread(font->oldfont, 1, datasize, fontfile); //read raw data
1787 if (font->ft_flags & FT_COLOR) { //remap palette
1788 ubyte palette[256*3];
1789 ubyte colormap[256];
1792 cfseek(fontfile,-sizeof(palette),SEEK_END);
1794 cfread(palette,3,256,fontfile); //read the palette
1796 #ifdef MACINTOSH // swap the first and last palette entries (black and white)
1801 for (i = 0; i < 3; i++) {
1803 palette[i] = palette[765+i];
1807 // we also need to swap the data entries as well. black is white and white is black
1809 for (i = 0; i < data_len; i++) {
1810 if (font->ft_data[i] == 0)
1811 font->ft_data[i] = 255;
1812 else if (font->ft_data[i] == 255)
1813 font->ft_data[i] = 0;
1819 build_colormap_good( (ubyte *)&palette, colormap, freq );
1821 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255;
1823 decode_data_asm(font->ft_data, data_len, colormap, freq );
1830 if (font->ft_bitmaps)
1831 d_free( font->ft_bitmaps );
1832 gr_free_bitmap_data(&font->ft_parent_bitmap);
1833 // ogl_freebmtexture(&font->ft_parent_bitmap);
1835 ogl_init_font(font);
1840 void gr_set_fontcolor( int fg, int bg )
1846 void gr_set_curfont( grs_font * new )
1852 int gr_internal_string_clipped(int x, int y, char *s )
1855 char * text_ptr, * next_row, * text_ptr1;
1856 int r, BitMask, i, bits, width, spacing, letter, underline;
1863 while (next_row != NULL )
1865 text_ptr1 = next_row;
1869 if (x==0x8000) //centered
1870 x = get_centered_x(text_ptr1);
1874 for (r=0; r<FHEIGHT; r++) {
1875 text_ptr = text_ptr1;
1879 if (*text_ptr == '\n' ) {
1880 next_row = &text_ptr[1];
1884 if (*text_ptr == CC_COLOR) {
1885 FG_COLOR = *(text_ptr+1);
1890 if (*text_ptr == CC_LSPACING) {
1891 Int3(); // Warning: skip lines not supported for clipped strings.
1897 if (*text_ptr == CC_UNDERLINE ) {
1898 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1903 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1905 letter = *text_ptr-FMINCHAR;
1907 if (!INFONT(letter)) { //not in font, draw as space
1913 if (FFLAGS & FT_PROPORTIONAL)
1914 fp = FCHARS[letter];
1916 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1919 for (i=0; i< width; i++ ) {
1920 gr_setcolor(FG_COLOR);
1924 fp += BITS_TO_BYTES(width)*r;
1928 for (i=0; i< width; i++ ) {
1934 gr_setcolor(FG_COLOR);
1936 gr_setcolor(BG_COLOR);
1942 x += spacing-width; //for kerning
1952 int gr_internal_string_clipped_m(int x, int y, char *s )
1955 char * text_ptr, * next_row, * text_ptr1;
1956 int r, BitMask, i, bits, width, spacing, letter, underline;
1963 while (next_row != NULL )
1965 text_ptr1 = next_row;
1969 if (x==0x8000) //centered
1970 x = get_centered_x(text_ptr1);
1974 for (r=0; r<FHEIGHT; r++) {
1977 text_ptr = text_ptr1;
1980 if (*text_ptr == '\n' ) {
1981 next_row = &text_ptr[1];
1985 if (*text_ptr == CC_COLOR) {
1986 FG_COLOR = *(text_ptr+1);
1991 if (*text_ptr == CC_LSPACING) {
1992 Int3(); // Warning: skip lines not supported for clipped strings.
1998 if (*text_ptr == CC_UNDERLINE ) {
1999 if ((r==FBASELINE+2) || (r==FBASELINE+3))
2004 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
2006 letter = *text_ptr-FMINCHAR;
2008 if (!INFONT(letter)) { //not in font, draw as space
2014 if (FFLAGS & FT_PROPORTIONAL)
2015 fp = FCHARS[letter];
2017 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
2020 for (i=0; i< width; i++ ) {
2021 gr_setcolor(FG_COLOR);
2025 fp += BITS_TO_BYTES(width)*r;
2029 for (i=0; i< width; i++ ) {
2034 if (bits & BitMask) {
2035 gr_setcolor(FG_COLOR);
2044 x += spacing-width; //for kerning