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-04 03:58:25 $
19 * Graphical routines for drawing fonts.
21 * $Log: not supported by cvs2svn $
22 * Revision 1.7 2001/11/02 10:46:23 bradleyb
23 * fixed gr_remap_font, minor stuff
25 * Revision 1.6 2001/11/02 02:03:35 bradleyb
26 * Enable OpenGL fonts\!
43 #include "pa_enabl.h" //$$POLY_ACC
59 #define MAX_OPEN_FONTS 50
60 #define FILENAME_LEN 13
62 typedef struct openfont {
63 char filename[FILENAME_LEN];
67 //list of open fonts, for use (for now) for palette remapping
68 openfont open_font[MAX_OPEN_FONTS];
70 #define FONT grd_curcanv->cv_font
71 #define FG_COLOR grd_curcanv->cv_font_fg_color
72 #define BG_COLOR grd_curcanv->cv_font_bg_color
73 #define FWIDTH FONT->ft_w
74 #define FHEIGHT FONT->ft_h
75 #define FBASELINE FONT->ft_baseline
76 #define FFLAGS FONT->ft_flags
77 #define FMINCHAR FONT->ft_minchar
78 #define FMAXCHAR FONT->ft_maxchar
79 #define FDATA FONT->ft_data
80 #define FCHARS FONT->ft_chars
81 #define FWIDTHS FONT->ft_widths
83 #define BITS_TO_BYTES(x) (((x)+7)>>3)
85 int gr_internal_string_clipped(int x, int y, char *s );
86 int gr_internal_string_clipped_m(int x, int y, char *s );
88 ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second)
90 ubyte *p=font->ft_kerndata;
93 if (p[0]==first && p[1]==second)
101 //takes the character AFTER being offset into font
102 #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
104 //takes the character BEFORE being offset into current font
105 void get_char_width(ubyte c,ubyte c2,int *width,int *spacing)
111 if (!INFONT(letter)) { //not in font, draw as space
113 if (FFLAGS & FT_PROPORTIONAL)
120 if (FFLAGS & FT_PROPORTIONAL)
121 *width = FWIDTHS[letter];
127 if (FFLAGS & FT_KERNED) {
130 if (!(c2==0 || c2=='\n')) {
133 letter2 = c2-FMINCHAR;
135 if (INFONT(letter2)) {
137 p = find_kern_entry(FONT,(ubyte)letter,letter2);
146 int get_centered_x(char *s)
150 for (w=0;*s!=0 && *s!='\n';s++) {
154 continue;//skip color codes.
156 get_char_width(s[0],s[1],&w2,&s2);
160 return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
163 //hack to allow color codes to be embedded in strings -MPM
164 //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string.
165 //function must already have orig_color var set (or they could be passed as args...)
166 //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain
167 int gr_message_color_level=1;
168 #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x03)) { \
171 if (gr_message_color_level >= *(text_ptr-1)) \
172 FG_COLOR = *text_ptr - 1; \
176 else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \
177 if (gr_message_color_level >= *text_ptr - 3) \
178 FG_COLOR=orig_color; \
182 int gr_internal_string0(int x, int y, char *s )
185 ubyte * text_ptr, * next_row, * text_ptr1;
186 int r, BitMask, i, bits, width, spacing, letter, underline;
189 unsigned int VideoOffset, VideoOffset1;
193 VideoOffset1 = y * ROWSIZE + x;
197 while (next_row != NULL )
199 text_ptr1 = next_row;
202 if (x==0x8000) { //centered
203 int xx = get_centered_x(text_ptr1);
204 VideoOffset1 = y * ROWSIZE + xx;
207 for (r=0; r<FHEIGHT; r++)
210 text_ptr = text_ptr1;
212 VideoOffset = VideoOffset1;
216 if (*text_ptr == '\n' )
218 next_row = &text_ptr[1];
222 if (*text_ptr == CC_COLOR) {
223 FG_COLOR = *(text_ptr+1);
228 if (*text_ptr == CC_LSPACING) {
229 skip_lines = *(text_ptr+1) - '0';
235 if (*text_ptr == CC_UNDERLINE )
237 if ((r==FBASELINE+2) || (r==FBASELINE+3))
242 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
244 letter = *text_ptr-FMINCHAR;
246 if (!INFONT(letter)) { //not in font, draw as space
247 VideoOffset += spacing;
252 if (FFLAGS & FT_PROPORTIONAL)
255 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
258 for (i=0; i< width; i++ )
259 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
262 fp += BITS_TO_BYTES(width)*r;
266 for (i=0; i< width; i++ )
274 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
276 DATA[VideoOffset++] = (unsigned char) BG_COLOR;
281 VideoOffset += spacing-width; //for kerning
286 VideoOffset1 += ROWSIZE; y++;
290 VideoOffset1 += ROWSIZE * skip_lines;
296 int gr_internal_string0m(int x, int y, char *s )
299 ubyte * text_ptr, * next_row, * text_ptr1;
300 int r, BitMask, i, bits, width, spacing, letter, underline;
303 unsigned int VideoOffset, VideoOffset1;
305 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
309 VideoOffset1 = y * ROWSIZE + x;
313 while (next_row != NULL )
315 text_ptr1 = next_row;
318 if (x==0x8000) { //centered
319 int xx = get_centered_x(text_ptr1);
320 VideoOffset1 = y * ROWSIZE + xx;
323 for (r=0; r<FHEIGHT; r++)
326 text_ptr = text_ptr1;
328 VideoOffset = VideoOffset1;
332 if (*text_ptr == '\n' )
334 next_row = &text_ptr[1];
338 if (*text_ptr == CC_COLOR) {
339 FG_COLOR = *(text_ptr+1);
344 if (*text_ptr == CC_LSPACING) {
345 skip_lines = *(text_ptr+1) - '0';
351 if (*text_ptr == CC_UNDERLINE )
353 if ((r==FBASELINE+2) || (r==FBASELINE+3))
358 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
360 letter = *text_ptr-FMINCHAR;
362 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
363 CHECK_EMBEDDED_COLORS() else{
364 VideoOffset += spacing;
370 if (FFLAGS & FT_PROPORTIONAL)
373 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
376 for (i=0; i< width; i++ )
377 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
380 fp += BITS_TO_BYTES(width)*r;
384 for (i=0; i< width; i++ )
392 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
400 VideoOffset += spacing-width;
403 VideoOffset1 += ROWSIZE;
407 VideoOffset1 += ROWSIZE * skip_lines;
414 int gr_internal_string2(int x, int y, char *s )
417 ubyte * text_ptr, * next_row, * text_ptr1;
418 int r, BitMask, i, bits, width, spacing, letter, underline;
419 int page_switched, skip_lines = 0;
421 unsigned int VideoOffset, VideoOffset1;
423 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
427 gr_vesa_setpage(VideoOffset1 >> 16);
429 VideoOffset1 &= 0xFFFF;
433 while (next_row != NULL )
435 text_ptr1 = next_row;
438 if (x==0x8000) { //centered
439 int xx = get_centered_x(text_ptr1);
440 VideoOffset1 = y * ROWSIZE + xx;
441 gr_vesa_setpage(VideoOffset1 >> 16);
442 VideoOffset1 &= 0xFFFF;
445 for (r=0; r<FHEIGHT; r++)
447 text_ptr = text_ptr1;
449 VideoOffset = VideoOffset1;
455 if (*text_ptr == '\n' )
457 next_row = &text_ptr[1];
461 if (*text_ptr == CC_COLOR) {
462 FG_COLOR = *(text_ptr+1);
467 if (*text_ptr == CC_LSPACING) {
468 skip_lines = *(text_ptr+1) - '0';
474 if (*text_ptr == CC_UNDERLINE )
476 if ((r==FBASELINE+2) || (r==FBASELINE+3))
481 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
483 Assert(width==spacing); //no kerning support here
485 letter = *text_ptr-FMINCHAR;
487 if (!INFONT(letter)) { //not in font, draw as space
488 VideoOffset += spacing;
493 if (FFLAGS & FT_PROPORTIONAL)
496 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
500 if ( VideoOffset+width > 0xFFFF )
502 for (i=0; i< width; i++ )
504 gr_video_memory[VideoOffset++] = FG_COLOR;
506 if (VideoOffset > 0xFFFF )
508 VideoOffset -= 0xFFFF + 1;
516 for (i=0; i< width; i++ )
517 gr_video_memory[VideoOffset++] = FG_COLOR;
526 fp += BITS_TO_BYTES(width)*r;
530 if ( VideoOffset+width > 0xFFFF )
532 for (i=0; i< width; i++ )
540 gr_video_memory[VideoOffset++] = FG_COLOR;
542 gr_video_memory[VideoOffset++] = BG_COLOR;
546 if (VideoOffset > 0xFFFF )
548 VideoOffset -= 0xFFFF + 1;
560 if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR;
561 else gr_video_memory[VideoOffset+0] = BG_COLOR;
563 if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR;
564 else gr_video_memory[VideoOffset+1] = BG_COLOR;
566 if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR;
567 else gr_video_memory[VideoOffset+2] = BG_COLOR;
569 if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR;
570 else gr_video_memory[VideoOffset+3] = BG_COLOR;
572 if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR;
573 else gr_video_memory[VideoOffset+4] = BG_COLOR;
575 if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR;
576 else gr_video_memory[VideoOffset+5] = BG_COLOR;
578 if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR;
579 else gr_video_memory[VideoOffset+6] = BG_COLOR;
581 if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR;
582 else gr_video_memory[VideoOffset+7] = BG_COLOR;
586 for (i=0; i< width/2 ; i++ )
594 gr_video_memory[VideoOffset++] = FG_COLOR;
596 gr_video_memory[VideoOffset++] = BG_COLOR;
608 gr_video_memory[VideoOffset++] = FG_COLOR;
610 gr_video_memory[VideoOffset++] = BG_COLOR;
620 VideoOffset1 += ROWSIZE;
622 if (VideoOffset1 > 0xFFFF ) {
623 VideoOffset1 -= 0xFFFF + 1;
630 VideoOffset1 += ROWSIZE * skip_lines;
636 int gr_internal_string2m(int x, int y, char *s )
639 char * text_ptr, * next_row, * text_ptr1;
640 int r, BitMask, i, bits, width, spacing, letter, underline;
641 int page_switched, skip_lines = 0;
643 unsigned int VideoOffset, VideoOffset1;
645 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
647 gr_vesa_setpage(VideoOffset1 >> 16);
649 VideoOffset1 &= 0xFFFF;
653 while (next_row != NULL )
655 text_ptr1 = next_row;
658 if (x==0x8000) { //centered
659 int xx = get_centered_x(text_ptr1);
660 VideoOffset1 = y * ROWSIZE + xx;
661 gr_vesa_setpage(VideoOffset1 >> 16);
662 VideoOffset1 &= 0xFFFF;
665 for (r=0; r<FHEIGHT; r++)
667 text_ptr = text_ptr1;
669 VideoOffset = VideoOffset1;
675 if (*text_ptr == '\n' )
677 next_row = &text_ptr[1];
681 if (*text_ptr == CC_COLOR) {
682 FG_COLOR = *(text_ptr+1);
687 if (*text_ptr == CC_LSPACING) {
688 skip_lines = *(text_ptr+1) - '0';
694 if (*text_ptr == CC_UNDERLINE )
696 if ((r==FBASELINE+2) || (r==FBASELINE+3))
701 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
703 letter = *text_ptr-FMINCHAR;
705 if (!INFONT(letter)) { //not in font, draw as space
706 VideoOffset += width;
711 if (FFLAGS & FT_PROPORTIONAL)
714 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
718 if ( VideoOffset+width > 0xFFFF )
720 for (i=0; i< width; i++ )
722 gr_video_memory[VideoOffset++] = FG_COLOR;
724 if (VideoOffset > 0xFFFF )
726 VideoOffset -= 0xFFFF + 1;
734 for (i=0; i< width; i++ )
735 gr_video_memory[VideoOffset++] = FG_COLOR;
740 fp += BITS_TO_BYTES(width)*r;
744 if ( VideoOffset+width > 0xFFFF )
746 for (i=0; i< width; i++ )
754 gr_video_memory[VideoOffset++] = FG_COLOR;
760 if (VideoOffset > 0xFFFF )
762 VideoOffset -= 0xFFFF + 1;
769 for (i=0; i< width; i++ )
777 gr_video_memory[VideoOffset++] = FG_COLOR;
786 VideoOffset += spacing-width;
790 VideoOffset1 += ROWSIZE;
792 if (VideoOffset1 > 0xFFFF ) {
793 VideoOffset1 -= 0xFFFF + 1;
800 VideoOffset1 += ROWSIZE * skip_lines;
806 #endif // __ENV_MSDOS__
808 #if defined(POLY_ACC)
809 int gr_internal_string5(int x, int y, char *s )
812 ubyte * text_ptr, * next_row, * text_ptr1;
813 int r, BitMask, i, bits, width, spacing, letter, underline;
816 unsigned int VideoOffset, VideoOffset1;
819 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
823 while (next_row != NULL )
825 text_ptr1 = next_row;
828 if (x==0x8000) { //centered
829 int xx = get_centered_x(text_ptr1);
830 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
833 for (r=0; r<FHEIGHT; r++)
836 text_ptr = text_ptr1;
838 VideoOffset = VideoOffset1;
842 if (*text_ptr == '\n' )
844 next_row = &text_ptr[1];
848 if (*text_ptr == CC_COLOR) {
849 FG_COLOR = *(text_ptr+1);
854 if (*text_ptr == CC_LSPACING) {
855 skip_lines = *(text_ptr+1) - '0';
861 if (*text_ptr == CC_UNDERLINE )
863 if ((r==FBASELINE+2) || (r==FBASELINE+3))
868 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
870 letter = *text_ptr-FMINCHAR;
872 if (!INFONT(letter)) { //not in font, draw as space
873 VideoOffset += spacing * PA_BPP;
878 if (FFLAGS & FT_PROPORTIONAL)
881 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
884 for (i=0; i< width; i++ )
885 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
888 fp += BITS_TO_BYTES(width)*r;
892 for (i=0; i< width; i++ )
900 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
902 { *(short *)(DATA + VideoOffset) = pa_clut[BG_COLOR]; VideoOffset += PA_BPP; }
907 VideoOffset += PA_BPP * (spacing-width); //for kerning
912 VideoOffset1 += ROWSIZE; y++;
916 VideoOffset1 += ROWSIZE * skip_lines;
922 int gr_internal_string5m(int x, int y, char *s )
925 ubyte * text_ptr, * next_row, * text_ptr1;
926 int r, BitMask, i, bits, width, spacing, letter, underline;
929 unsigned int VideoOffset, VideoOffset1;
932 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
936 while (next_row != NULL )
938 text_ptr1 = next_row;
941 if (x==0x8000) { //centered
942 int xx = get_centered_x(text_ptr1);
943 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
946 for (r=0; r<FHEIGHT; r++)
949 text_ptr = text_ptr1;
951 VideoOffset = VideoOffset1;
955 if (*text_ptr == '\n' )
957 next_row = &text_ptr[1];
961 if (*text_ptr == CC_COLOR) {
962 FG_COLOR = *(text_ptr+1);
967 if (*text_ptr == CC_LSPACING) {
968 skip_lines = *(text_ptr+1) - '0';
974 if (*text_ptr == CC_UNDERLINE )
976 if ((r==FBASELINE+2) || (r==FBASELINE+3))
981 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
983 letter = *text_ptr-FMINCHAR;
985 if (!INFONT(letter)) { //not in font, draw as space
986 VideoOffset += spacing * PA_BPP;
991 if (FFLAGS & FT_PROPORTIONAL)
994 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
997 for (i=0; i< width; i++ )
998 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
1001 fp += BITS_TO_BYTES(width)*r;
1005 for (i=0; i< width; i++ )
1013 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
1015 VideoOffset += PA_BPP;
1021 VideoOffset += PA_BPP * (spacing-width);
1024 VideoOffset1 += ROWSIZE; y++;
1027 VideoOffset1 += ROWSIZE * skip_lines;
1035 //a bitmap for the character
1036 grs_bitmap char_bm = {
1039 BM_FLAG_TRANSPARENT, //flags
1042 #ifdef BITMAP_SELECTOR
1049 int gr_internal_color_string(int x, int y, char *s )
1052 ubyte * text_ptr, * next_row, * text_ptr1;
1053 int width, spacing,letter;
1056 char_bm.bm_h = FHEIGHT; //set height for chars of this font
1063 while (next_row != NULL)
1065 text_ptr1 = next_row;
1068 text_ptr = text_ptr1;
1072 if (xx==0x8000) //centered
1073 xx = get_centered_x(text_ptr);
1077 if (*text_ptr == '\n' )
1079 next_row = &text_ptr[1];
1084 letter = *text_ptr-FMINCHAR;
1086 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1088 if (!INFONT(letter)) { //not in font, draw as space
1094 if (FFLAGS & FT_PROPORTIONAL)
1095 fp = FCHARS[letter];
1097 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1099 gr_init_bitmap (&char_bm, BM_LINEAR, 0, 0, width, FHEIGHT, width, fp);
1100 gr_bitmapm(xx,yy,&char_bm);
1112 #include "../main/inferno.h"
1113 #include "ogl_init.h"
1115 //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
1117 int pow2ize(int x);//from ogl.c
1119 int get_font_total_width(grs_font * font){
1120 if (font->ft_flags & FT_PROPORTIONAL){
1121 int i,w=0,c=font->ft_minchar;
1122 for (i=0;c<=font->ft_maxchar;i++,c++){
1123 if (font->ft_widths[i]<0)
1125 w+=font->ft_widths[i];
1129 return font->ft_w*(font->ft_maxchar-font->ft_minchar+1);
1132 void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){
1133 int nchars = font->ft_maxchar-font->ft_minchar+1;
1134 int r,x,y,nc=0,smallest=999999,smallr=-1,tries;
1135 int smallprop=10000;
1137 for (h=32;h<=256;h*=2){
1138 // h=pow2ize(font->ft_h*rows+gap*(rows-1));
1139 if (font->ft_h>h)continue;
1140 r=(h/(font->ft_h+gap));
1141 w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r);
1147 mprintf((0,"failed to fit (%ix%i, %ic)\n",w,h,nc));
1152 while(y+font->ft_h<=h){
1157 if (font->ft_flags & FT_PROPORTIONAL){
1158 if (x+font->ft_widths[nc]+gap>w)break;
1159 x+=font->ft_widths[nc++]+gap;
1161 if (x+font->ft_w+gap>w)break;
1175 mprintf((0,"fit: %ix%i %i tries\n",w,h,tries));
1177 if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32)
1198 Error("couldn't fit font?\n");
1199 mprintf((0,"using %ix%i\n",*rw,*rh));
1203 void ogl_init_font(grs_font * font){
1204 int nchars = font->ft_maxchar-font->ft_minchar+1;
1205 int i,w,h,tw,th,x,y,curx=0,cury=0;
1207 // char data[32*32*4];
1209 int gap=0;//having a gap just wastes ram, since we don't filter text textures at all.
1211 ogl_font_choose_size(font,gap,&tw,&th);
1212 data=d_malloc(tw*th);
1213 gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data);
1215 font->ft_parent_bitmap.gltexture=ogl_get_free_texture();
1217 font->ft_bitmaps=(grs_bitmap*)d_malloc( nchars * sizeof(grs_bitmap));
1218 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));
1223 for(i=0;i<nchars;i++){
1224 // s[0]=font->ft_minchar+i;
1225 // gr_get_string_size(s,&w,&h,&aw);
1226 if (font->ft_flags & FT_PROPORTIONAL)
1227 w=font->ft_widths[i];
1230 // mprintf((0,"char %i(%ix%i): ",i,w,h));
1232 mprintf((0,"grr\n"));continue;
1239 Error("font doesn't really fit (%i/%i)?\n",i,nchars);
1240 if (font->ft_flags & FT_COLOR) {
1241 if (font->ft_flags & FT_PROPORTIONAL)
1242 fp = font->ft_chars[i];
1244 fp = font->ft_data + i * w*h;
1247 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w];
1250 // gr_init_bitmap(&font->ft_bitmaps[i],BM_LINEAR,0,0,w,h,w,font->);
1252 int BitMask,bits=0,white=gr_find_closest_color(63,63,63);
1253 // if (w*h>sizeof(data))
1254 // Error("ogl_init_font: toobig\n");
1255 if (font->ft_flags & FT_PROPORTIONAL)
1256 fp = font->ft_chars[i];
1258 fp = font->ft_data + i * BITS_TO_BYTES(w)*h;
1261 for (x=0; x< w; x++ )
1269 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white;
1271 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255;
1276 gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h);
1280 if (!(font->ft_flags & FT_COLOR)) {
1281 //use GL_INTENSITY instead of GL_RGB
1282 if (ogl_intensity4_ok){
1283 font->ft_parent_bitmap.gltexture->internalformat=GL_INTENSITY4;
1284 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE;
1285 }else if (ogl_luminance4_alpha4_ok){
1286 font->ft_parent_bitmap.gltexture->internalformat=GL_LUMINANCE4_ALPHA4;
1287 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE_ALPHA;
1288 }else if (ogl_rgba2_ok){
1289 font->ft_parent_bitmap.gltexture->internalformat=GL_RGBA2;
1290 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1292 font->ft_parent_bitmap.gltexture->internalformat=ogl_rgba_format;
1293 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1296 ogl_loadbmtexture_m(&font->ft_parent_bitmap,0);
1299 int ogl_internal_string(int x, int y, char *s )
1301 ubyte * text_ptr, * next_row, * text_ptr1;
1302 int width, spacing,letter;
1304 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
1310 if (grd_curscreen->sc_canvas.cv_bitmap.bm_type != BM_OGL)
1312 while (next_row != NULL)
1314 text_ptr1 = next_row;
1317 text_ptr = text_ptr1;
1321 if (xx==0x8000) //centered
1322 xx = get_centered_x(text_ptr);
1326 if (*text_ptr == '\n' )
1328 next_row = &text_ptr[1];
1333 letter = *text_ptr-FMINCHAR;
1335 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1337 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
1338 CHECK_EMBEDDED_COLORS() else{
1345 // ogl_ubitblt(FONT->ft_bitmaps[letter].bm_w,FONT->ft_bitmaps[letter].bm_h,xx,yy,0,0,&FONT->ft_bitmaps[letter],NULL);
1346 // if (*text_ptr>='0' && *text_ptr<='9'){
1347 if (FFLAGS&FT_COLOR)
1348 gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);
1350 if (grd_curcanv->cv_bitmap.bm_type==BM_OGL)
1351 ogl_ubitmapm_c(xx,yy,&FONT->ft_bitmaps[letter],FG_COLOR);
1353 Error("ogl_internal_string: non-color string to non-ogl dest\n");
1354 // gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);//ignores color..
1367 int gr_internal_color_string(int x, int y, char *s ){
1368 return ogl_internal_string(x,y,s);
1372 int gr_string(int x, int y, char *s )
1377 Assert(FONT != NULL);
1379 if ( x == 0x8000 ) {
1380 if ( y<0 ) clipped |= 1;
1381 gr_get_string_size(s, &w, &h, &aw );
1382 // for x, since this will be centered, only look at
1384 if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1385 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1387 if ( (y+h) < 0 ) clipped |= 2;
1388 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1391 if ( (x<0) || (y<0) ) clipped |= 1;
1392 gr_get_string_size(s, &w, &h, &aw );
1393 if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1394 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1395 if ( (x+w) < 0 ) clipped |= 2;
1396 if ( (y+h) < 0 ) clipped |= 2;
1397 if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;
1398 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1402 return gr_ustring(x, y, s );
1404 if ( clipped & 2 ) {
1405 // Completely clipped...
1406 mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
1410 if ( clipped & 1 ) {
1411 // Partially clipped...
1412 //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
1415 // Partially clipped...
1418 return ogl_internal_string(x,y,s);
1421 if (FFLAGS & FT_COLOR)
1422 return gr_internal_color_string( x, y, s);
1424 if ( BG_COLOR == -1)
1425 return gr_internal_string_clipped_m( x, y, s );
1427 return gr_internal_string_clipped( x, y, s );
1430 int gr_ustring(int x, int y, char *s )
1434 return ogl_internal_string(x,y,s);
1437 if (FFLAGS & FT_COLOR) {
1439 return gr_internal_color_string(x,y,s);
1446 if ( BG_COLOR == -1)
1447 return gr_internal_string0m(x,y,s);
1449 return gr_internal_string0(x,y,s);
1450 #ifdef __ENV_MSDOS__
1452 if ( BG_COLOR == -1)
1453 return gr_internal_string2m(x,y,s);
1455 return gr_internal_string2(x,y,s);
1456 #endif // __ENV_MSDOS__
1457 #if defined(POLY_ACC)
1459 if ( BG_COLOR == -1)
1460 return gr_internal_string5m(x,y,s);
1462 return gr_internal_string5(x,y,s);
1469 void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width )
1471 int i = 0, longest_width = 0;
1474 *string_height = FHEIGHT;
1476 *average_width = FWIDTH;
1483 // if (*s == CC_UNDERLINE)
1488 *string_height += FHEIGHT;
1494 // 1 = next byte specifies color, so skip the 1 and the color value
1497 else if (*s == CC_LSPACING) {
1498 *string_height += *(s+1)-'0';
1501 get_char_width(s[0],s[1],&width,&spacing);
1503 *string_width += spacing;
1505 if (*string_width > longest_width)
1506 longest_width = *string_width;
1513 *string_width = longest_width;
1517 int gr_uprintf( int x, int y, char * format, ... )
1522 va_start(args, format );
1523 vsprintf(buffer,format,args);
1524 return gr_ustring( x, y, buffer );
1527 int gr_printf( int x, int y, char * format, ... )
1532 va_start(args, format );
1533 vsprintf(buffer,format,args);
1534 return gr_string( x, y, buffer );
1537 void gr_close_font( grs_font * font )
1544 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=font;fontnum++);
1545 Assert(fontnum<MAX_OPEN_FONTS); //did we find slot?
1547 open_font[fontnum].ptr = NULL;
1549 if ( font->ft_chars )
1550 d_free( font->ft_chars );
1551 d_free( font->oldfont );
1553 if (font->ft_bitmaps)
1554 d_free( font->ft_bitmaps );
1555 gr_free_bitmap_data(&font->ft_parent_bitmap);
1556 // ogl_freebmtexture(&font->ft_parent_bitmap);
1563 //remap (by re-reading) all the color fonts
1564 void gr_remap_color_fonts()
1568 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1571 font = open_font[fontnum].ptr;
1573 if (font && (font->ft_flags & FT_COLOR))
1574 gr_remap_font(font,open_font[fontnum].filename);
1578 void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq );
1579 void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count );
1581 #pragma aux decode_data_asm parm [esi] [ecx] [edi] [ebx] modify exact [esi edi eax ebx ecx] = \
1585 "inc dword ptr [ebx+eax*4]" \
1586 "mov al,[edi+eax]" \
1594 grs_font * gr_init_font( char * fontname )
1596 static int first_time=1;
1600 unsigned char * ptr;
1604 int32_t datasize; //size up to (but not including) palette
1608 for (i=0;i<MAX_OPEN_FONTS;i++)
1609 open_font[i].ptr = NULL;
1613 //find free font slot
1614 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=NULL;fontnum++);
1615 Assert(fontnum<MAX_OPEN_FONTS); //did we find one?
1617 strncpy(open_font[fontnum].filename,fontname,FILENAME_LEN);
1619 fontfile = cfopen(fontname, "rb");
1622 Error( "Can't open font file %s", fontname );
1624 cfread(&file_id,sizeof(file_id),1,fontfile);
1625 file_id=swapint(file_id);
1626 cfread(&datasize,sizeof(datasize),1,fontfile);
1627 datasize=swapint(datasize);
1629 if (file_id != 0x4e465350) /* 'NFSP' */
1630 Error( "File %s is not a font file", fontname );
1632 font = (old_grs_font *) d_malloc(datasize);
1633 newfont = (grs_font *) d_malloc(sizeof(grs_font));
1634 newfont->oldfont=font;
1636 open_font[fontnum].ptr = newfont;
1638 cfread(font,1,datasize,fontfile);
1640 newfont->ft_flags=swapint(font->ft_flags);
1641 newfont->ft_w=swapshort(font->ft_w);
1642 newfont->ft_h=swapshort(font->ft_h);
1643 newfont->ft_baseline=swapshort(font->ft_baseline);
1644 newfont->ft_maxchar=font->ft_maxchar;
1645 newfont->ft_minchar=font->ft_minchar;
1646 newfont->ft_bytewidth=swapshort(font->ft_bytewidth);
1648 nchars = newfont->ft_maxchar-newfont->ft_minchar+1;
1650 if (newfont->ft_flags & FT_PROPORTIONAL) {
1652 newfont->ft_widths = (short *) (swapint(font->ft_widths) + ((ubyte *) font));
1653 newfont->ft_data = (swapint(font->ft_data)) + ((ubyte *) font);
1654 newfont->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1656 ptr = newfont->ft_data;
1658 for (i=0; i< nchars; i++ ) {
1659 newfont->ft_chars[i] = ptr;
1660 if (newfont->ft_flags & FT_COLOR)
1661 ptr += newfont->ft_widths[i] * newfont->ft_h;
1663 ptr += BITS_TO_BYTES(newfont->ft_widths[i]) * newfont->ft_h;
1668 newfont->ft_data = ((unsigned char *) font) + sizeof(*font);
1669 newfont->ft_chars = NULL;
1670 newfont->ft_widths = NULL;
1672 ptr = newfont->ft_data + (nchars * newfont->ft_w * newfont->ft_h);
1675 if (newfont->ft_flags & FT_KERNED)
1676 newfont->ft_kerndata = swapint(font->ft_kerndata) + ((ubyte *) font);
1678 if (newfont->ft_flags & FT_COLOR) { //remap palette
1679 ubyte palette[256*3];
1680 ubyte colormap[256];
1683 cfread(palette,3,256,fontfile); //read the palette
1685 #ifdef MACINTOSH // swap the first and last palette entries (black and white)
1690 for (i = 0; i < 3; i++) {
1692 palette[i] = palette[765+i];
1696 // we also need to swap the data entries as well. black is white and white is black
1698 for (i = 0; i < ptr-newfont->ft_data; i++) {
1699 if (newfont->ft_data[i] == 0)
1700 newfont->ft_data[i] = 255;
1701 else if (newfont->ft_data[i] == 255)
1702 newfont->ft_data[i] = 0;
1708 build_colormap_good( (ubyte *)&palette, colormap, freq );
1710 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // chaged from colormap[255] = 255 to this for macintosh
1712 decode_data_asm(newfont->ft_data, ptr-newfont->ft_data, colormap, freq );
1718 // memcpy(newfont,font,(ubyte*)&newfont->oldfont-(ubyte*)newfont);//fill in newfont data from oldfont struct
1719 // mprintf((0,"%i %i %i\n",sizeof(grs_font),sizeof(old_grs_font),(ubyte*)&newfont->oldfont-(ubyte*)newfont));
1729 char tests[]="abcdefghij1234.A";
1730 gr_get_string_size(tests,&x,&y,&aw);
1731 // newfont->ft_aw=x/(float)strlen(tests);
1735 ogl_init_font(newfont);
1742 //remap a font by re-reading its data & palette
1743 void gr_remap_font( grs_font *font, char * fontname )
1749 int32_t datasize; //size up to (but not including) palette
1752 if (! (font->ft_flags & FT_COLOR))
1755 fontfile = cfopen(fontname, "rb");
1758 Error( "Can't open font file %s", fontname );
1760 file_id = cfile_read_int(fontfile);
1761 datasize = cfile_read_int(fontfile);
1763 if (file_id != 0x4e465350) /* 'NFSP' */
1764 Error( "File %s is not a font file", fontname );
1766 nchars = font->ft_maxchar-font->ft_minchar+1;
1768 //compute data length
1770 if (font->ft_flags & FT_PROPORTIONAL) {
1772 for (i=0; i< nchars; i++ ) {
1773 if (font->ft_flags & FT_COLOR)
1774 data_len += font->ft_widths[i] * font->ft_h;
1776 data_len += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1780 data_len = nchars * font->ft_w * font->ft_h;
1782 cfread(font->oldfont, 1, datasize, fontfile); //read raw data
1784 if (font->ft_flags & FT_COLOR) { //remap palette
1785 ubyte palette[256*3];
1786 ubyte colormap[256];
1789 cfseek(fontfile,-sizeof(palette),SEEK_END);
1791 cfread(palette,3,256,fontfile); //read the palette
1793 #ifdef MACINTOSH // swap the first and last palette entries (black and white)
1798 for (i = 0; i < 3; i++) {
1800 palette[i] = palette[765+i];
1804 // we also need to swap the data entries as well. black is white and white is black
1806 for (i = 0; i < data_len; i++) {
1807 if (font->ft_data[i] == 0)
1808 font->ft_data[i] = 255;
1809 else if (font->ft_data[i] == 255)
1810 font->ft_data[i] = 0;
1816 build_colormap_good( (ubyte *)&palette, colormap, freq );
1818 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255;
1820 decode_data_asm(font->ft_data, data_len, colormap, freq );
1827 ogl_init_font(font);
1832 void gr_set_fontcolor( int fg, int bg )
1838 void gr_set_curfont( grs_font * new )
1844 int gr_internal_string_clipped(int x, int y, char *s )
1847 char * text_ptr, * next_row, * text_ptr1;
1848 int r, BitMask, i, bits, width, spacing, letter, underline;
1855 while (next_row != NULL )
1857 text_ptr1 = next_row;
1861 if (x==0x8000) //centered
1862 x = get_centered_x(text_ptr1);
1866 for (r=0; r<FHEIGHT; r++) {
1867 text_ptr = text_ptr1;
1871 if (*text_ptr == '\n' ) {
1872 next_row = &text_ptr[1];
1876 if (*text_ptr == CC_COLOR) {
1877 FG_COLOR = *(text_ptr+1);
1882 if (*text_ptr == CC_LSPACING) {
1883 Int3(); // Warning: skip lines not supported for clipped strings.
1889 if (*text_ptr == CC_UNDERLINE ) {
1890 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1895 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1897 letter = *text_ptr-FMINCHAR;
1899 if (!INFONT(letter)) { //not in font, draw as space
1905 if (FFLAGS & FT_PROPORTIONAL)
1906 fp = FCHARS[letter];
1908 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1911 for (i=0; i< width; i++ ) {
1912 gr_setcolor(FG_COLOR);
1916 fp += BITS_TO_BYTES(width)*r;
1920 for (i=0; i< width; i++ ) {
1926 gr_setcolor(FG_COLOR);
1928 gr_setcolor(BG_COLOR);
1934 x += spacing-width; //for kerning
1944 int gr_internal_string_clipped_m(int x, int y, char *s )
1947 char * text_ptr, * next_row, * text_ptr1;
1948 int r, BitMask, i, bits, width, spacing, letter, underline;
1955 while (next_row != NULL )
1957 text_ptr1 = next_row;
1961 if (x==0x8000) //centered
1962 x = get_centered_x(text_ptr1);
1966 for (r=0; r<FHEIGHT; r++) {
1969 text_ptr = text_ptr1;
1972 if (*text_ptr == '\n' ) {
1973 next_row = &text_ptr[1];
1977 if (*text_ptr == CC_COLOR) {
1978 FG_COLOR = *(text_ptr+1);
1983 if (*text_ptr == CC_LSPACING) {
1984 Int3(); // Warning: skip lines not supported for clipped strings.
1990 if (*text_ptr == CC_UNDERLINE ) {
1991 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1996 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1998 letter = *text_ptr-FMINCHAR;
2000 if (!INFONT(letter)) { //not in font, draw as space
2006 if (FFLAGS & FT_PROPORTIONAL)
2007 fp = FCHARS[letter];
2009 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
2012 for (i=0; i< width; i++ ) {
2013 gr_setcolor(FG_COLOR);
2017 fp += BITS_TO_BYTES(width)*r;
2021 for (i=0; i< width; i++ ) {
2026 if (bits & BitMask) {
2027 gr_setcolor(FG_COLOR);
2036 x += spacing-width; //for kerning