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.
26 #include "pa_enabl.h" //$$POLY_ACC
42 #define MAX_OPEN_FONTS 50
43 #define FILENAME_LEN 13
45 typedef struct openfont {
46 char filename[FILENAME_LEN];
50 //list of open fonts, for use (for now) for palette remapping
51 openfont open_font[MAX_OPEN_FONTS];
53 #define FONT grd_curcanv->cv_font
54 #define FG_COLOR grd_curcanv->cv_font_fg_color
55 #define BG_COLOR grd_curcanv->cv_font_bg_color
56 #define FWIDTH FONT->ft_w
57 #define FHEIGHT FONT->ft_h
58 #define FBASELINE FONT->ft_baseline
59 #define FFLAGS FONT->ft_flags
60 #define FMINCHAR FONT->ft_minchar
61 #define FMAXCHAR FONT->ft_maxchar
62 #define FDATA FONT->ft_data
63 #define FCHARS FONT->ft_chars
64 #define FWIDTHS FONT->ft_widths
66 #define BITS_TO_BYTES(x) (((x)+7)>>3)
68 int gr_internal_string_clipped(int x, int y, char *s );
69 int gr_internal_string_clipped_m(int x, int y, char *s );
71 ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second)
73 ubyte *p=font->ft_kerndata;
76 if (p[0]==first && p[1]==second)
84 //takes the character AFTER being offset into font
85 #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
87 //takes the character BEFORE being offset into current font
88 void get_char_width(ubyte c,ubyte c2,int *width,int *spacing)
94 if (!INFONT(letter)) { //not in font, draw as space
96 if (FFLAGS & FT_PROPORTIONAL)
103 if (FFLAGS & FT_PROPORTIONAL)
104 *width = FWIDTHS[letter];
110 if (FFLAGS & FT_KERNED) {
113 if (!(c2==0 || c2=='\n')) {
116 letter2 = c2-FMINCHAR;
118 if (INFONT(letter2)) {
120 p = find_kern_entry(FONT,(ubyte)letter,letter2);
129 int get_centered_x(char *s)
133 for (w=0;*s!=0 && *s!='\n';s++) {
137 continue;//skip color codes.
139 get_char_width(s[0],s[1],&w2,&s2);
143 return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
146 //hack to allow color codes to be embedded in strings -MPM
147 //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string.
148 //function must already have orig_color var set (or they could be passed as args...)
149 //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain
150 int gr_message_color_level=1;
151 #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x03)) { \
154 if (gr_message_color_level >= *(text_ptr-1)) \
155 FG_COLOR = *text_ptr - 1; \
159 else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \
160 if (gr_message_color_level >= *text_ptr - 3) \
161 FG_COLOR=orig_color; \
165 int gr_internal_string0(int x, int y, char *s )
168 ubyte * text_ptr, * next_row, * text_ptr1;
169 int r, BitMask, i, bits, width, spacing, letter, underline;
172 unsigned int VideoOffset, VideoOffset1;
176 VideoOffset1 = y * ROWSIZE + x;
180 while (next_row != NULL )
182 text_ptr1 = next_row;
185 if (x==0x8000) { //centered
186 int xx = get_centered_x(text_ptr1);
187 VideoOffset1 = y * ROWSIZE + xx;
190 for (r=0; r<FHEIGHT; r++)
193 text_ptr = text_ptr1;
195 VideoOffset = VideoOffset1;
199 if (*text_ptr == '\n' )
201 next_row = &text_ptr[1];
205 if (*text_ptr == CC_COLOR) {
206 FG_COLOR = *(text_ptr+1);
211 if (*text_ptr == CC_LSPACING) {
212 skip_lines = *(text_ptr+1) - '0';
218 if (*text_ptr == CC_UNDERLINE )
220 if ((r==FBASELINE+2) || (r==FBASELINE+3))
225 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
227 letter = *text_ptr-FMINCHAR;
229 if (!INFONT(letter)) { //not in font, draw as space
230 VideoOffset += spacing;
235 if (FFLAGS & FT_PROPORTIONAL)
238 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
241 for (i=0; i< width; i++ )
242 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
245 fp += BITS_TO_BYTES(width)*r;
249 for (i=0; i< width; i++ )
257 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
259 DATA[VideoOffset++] = (unsigned char) BG_COLOR;
264 VideoOffset += spacing-width; //for kerning
269 VideoOffset1 += ROWSIZE; y++;
273 VideoOffset1 += ROWSIZE * skip_lines;
279 int gr_internal_string0m(int x, int y, char *s )
282 ubyte * text_ptr, * next_row, * text_ptr1;
283 int r, BitMask, i, bits, width, spacing, letter, underline;
286 unsigned int VideoOffset, VideoOffset1;
288 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
292 VideoOffset1 = y * ROWSIZE + x;
296 while (next_row != NULL )
298 text_ptr1 = next_row;
301 if (x==0x8000) { //centered
302 int xx = get_centered_x(text_ptr1);
303 VideoOffset1 = y * ROWSIZE + xx;
306 for (r=0; r<FHEIGHT; r++)
309 text_ptr = text_ptr1;
311 VideoOffset = VideoOffset1;
315 if (*text_ptr == '\n' )
317 next_row = &text_ptr[1];
321 if (*text_ptr == CC_COLOR) {
322 FG_COLOR = *(text_ptr+1);
327 if (*text_ptr == CC_LSPACING) {
328 skip_lines = *(text_ptr+1) - '0';
334 if (*text_ptr == CC_UNDERLINE )
336 if ((r==FBASELINE+2) || (r==FBASELINE+3))
341 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
343 letter = *text_ptr-FMINCHAR;
345 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
346 CHECK_EMBEDDED_COLORS() else{
347 VideoOffset += spacing;
353 if (FFLAGS & FT_PROPORTIONAL)
356 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
359 for (i=0; i< width; i++ )
360 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
363 fp += BITS_TO_BYTES(width)*r;
367 for (i=0; i< width; i++ )
375 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
383 VideoOffset += spacing-width;
386 VideoOffset1 += ROWSIZE;
390 VideoOffset1 += ROWSIZE * skip_lines;
397 int gr_internal_string2(int x, int y, char *s )
400 ubyte * text_ptr, * next_row, * text_ptr1;
401 int r, BitMask, i, bits, width, spacing, letter, underline;
402 int page_switched, skip_lines = 0;
404 unsigned int VideoOffset, VideoOffset1;
406 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
410 gr_vesa_setpage(VideoOffset1 >> 16);
412 VideoOffset1 &= 0xFFFF;
416 while (next_row != NULL )
418 text_ptr1 = next_row;
421 if (x==0x8000) { //centered
422 int xx = get_centered_x(text_ptr1);
423 VideoOffset1 = y * ROWSIZE + xx;
424 gr_vesa_setpage(VideoOffset1 >> 16);
425 VideoOffset1 &= 0xFFFF;
428 for (r=0; r<FHEIGHT; r++)
430 text_ptr = text_ptr1;
432 VideoOffset = VideoOffset1;
438 if (*text_ptr == '\n' )
440 next_row = &text_ptr[1];
444 if (*text_ptr == CC_COLOR) {
445 FG_COLOR = *(text_ptr+1);
450 if (*text_ptr == CC_LSPACING) {
451 skip_lines = *(text_ptr+1) - '0';
457 if (*text_ptr == CC_UNDERLINE )
459 if ((r==FBASELINE+2) || (r==FBASELINE+3))
464 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
466 Assert(width==spacing); //no kerning support here
468 letter = *text_ptr-FMINCHAR;
470 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
471 CHECK_EMBEDDED_COLORS() else{
472 VideoOffset += spacing;
478 if (FFLAGS & FT_PROPORTIONAL)
481 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
485 if ( VideoOffset+width > 0xFFFF )
487 for (i=0; i< width; i++ )
489 gr_video_memory[VideoOffset++] = FG_COLOR;
491 if (VideoOffset > 0xFFFF )
493 VideoOffset -= 0xFFFF + 1;
501 for (i=0; i< width; i++ )
502 gr_video_memory[VideoOffset++] = FG_COLOR;
511 fp += BITS_TO_BYTES(width)*r;
515 if ( VideoOffset+width > 0xFFFF )
517 for (i=0; i< width; i++ )
525 gr_video_memory[VideoOffset++] = FG_COLOR;
527 gr_video_memory[VideoOffset++] = BG_COLOR;
531 if (VideoOffset > 0xFFFF )
533 VideoOffset -= 0xFFFF + 1;
545 if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR;
546 else gr_video_memory[VideoOffset+0] = BG_COLOR;
548 if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR;
549 else gr_video_memory[VideoOffset+1] = BG_COLOR;
551 if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR;
552 else gr_video_memory[VideoOffset+2] = BG_COLOR;
554 if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR;
555 else gr_video_memory[VideoOffset+3] = BG_COLOR;
557 if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR;
558 else gr_video_memory[VideoOffset+4] = BG_COLOR;
560 if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR;
561 else gr_video_memory[VideoOffset+5] = BG_COLOR;
563 if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR;
564 else gr_video_memory[VideoOffset+6] = BG_COLOR;
566 if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR;
567 else gr_video_memory[VideoOffset+7] = BG_COLOR;
571 for (i=0; i< width/2 ; i++ )
579 gr_video_memory[VideoOffset++] = FG_COLOR;
581 gr_video_memory[VideoOffset++] = BG_COLOR;
593 gr_video_memory[VideoOffset++] = FG_COLOR;
595 gr_video_memory[VideoOffset++] = BG_COLOR;
605 VideoOffset1 += ROWSIZE;
607 if (VideoOffset1 > 0xFFFF ) {
608 VideoOffset1 -= 0xFFFF + 1;
615 VideoOffset1 += ROWSIZE * skip_lines;
621 int gr_internal_string2m(int x, int y, char *s )
624 char * text_ptr, * next_row, * text_ptr1;
625 int r, BitMask, i, bits, width, spacing, letter, underline;
626 int page_switched, skip_lines = 0;
628 unsigned int VideoOffset, VideoOffset1;
630 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
632 gr_vesa_setpage(VideoOffset1 >> 16);
634 VideoOffset1 &= 0xFFFF;
638 while (next_row != NULL )
640 text_ptr1 = next_row;
643 if (x==0x8000) { //centered
644 int xx = get_centered_x(text_ptr1);
645 VideoOffset1 = y * ROWSIZE + xx;
646 gr_vesa_setpage(VideoOffset1 >> 16);
647 VideoOffset1 &= 0xFFFF;
650 for (r=0; r<FHEIGHT; r++)
652 text_ptr = text_ptr1;
654 VideoOffset = VideoOffset1;
660 if (*text_ptr == '\n' )
662 next_row = &text_ptr[1];
666 if (*text_ptr == CC_COLOR) {
667 FG_COLOR = *(text_ptr+1);
672 if (*text_ptr == CC_LSPACING) {
673 skip_lines = *(text_ptr+1) - '0';
679 if (*text_ptr == CC_UNDERLINE )
681 if ((r==FBASELINE+2) || (r==FBASELINE+3))
686 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
688 letter = *text_ptr-FMINCHAR;
690 if (!INFONT(letter)) { //not in font, draw as space
691 VideoOffset += width;
696 if (FFLAGS & FT_PROPORTIONAL)
699 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
703 if ( VideoOffset+width > 0xFFFF )
705 for (i=0; i< width; i++ )
707 gr_video_memory[VideoOffset++] = FG_COLOR;
709 if (VideoOffset > 0xFFFF )
711 VideoOffset -= 0xFFFF + 1;
719 for (i=0; i< width; i++ )
720 gr_video_memory[VideoOffset++] = FG_COLOR;
725 fp += BITS_TO_BYTES(width)*r;
729 if ( VideoOffset+width > 0xFFFF )
731 for (i=0; i< width; i++ )
739 gr_video_memory[VideoOffset++] = FG_COLOR;
745 if (VideoOffset > 0xFFFF )
747 VideoOffset -= 0xFFFF + 1;
754 for (i=0; i< width; i++ )
762 gr_video_memory[VideoOffset++] = FG_COLOR;
771 VideoOffset += spacing-width;
775 VideoOffset1 += ROWSIZE;
777 if (VideoOffset1 > 0xFFFF ) {
778 VideoOffset1 -= 0xFFFF + 1;
785 VideoOffset1 += ROWSIZE * skip_lines;
791 #endif // __ENV_MSDOS__
793 #if defined(POLY_ACC)
794 int gr_internal_string5(int x, int y, char *s )
797 ubyte * text_ptr, * next_row, * text_ptr1;
798 int r, BitMask, i, bits, width, spacing, letter, underline;
801 unsigned int VideoOffset, VideoOffset1;
804 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
808 while (next_row != NULL )
810 text_ptr1 = next_row;
813 if (x==0x8000) { //centered
814 int xx = get_centered_x(text_ptr1);
815 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
818 for (r=0; r<FHEIGHT; r++)
821 text_ptr = text_ptr1;
823 VideoOffset = VideoOffset1;
827 if (*text_ptr == '\n' )
829 next_row = &text_ptr[1];
833 if (*text_ptr == CC_COLOR) {
834 FG_COLOR = *(text_ptr+1);
839 if (*text_ptr == CC_LSPACING) {
840 skip_lines = *(text_ptr+1) - '0';
846 if (*text_ptr == CC_UNDERLINE )
848 if ((r==FBASELINE+2) || (r==FBASELINE+3))
853 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
855 letter = *text_ptr-FMINCHAR;
857 if (!INFONT(letter)) { //not in font, draw as space
858 VideoOffset += spacing * PA_BPP;
863 if (FFLAGS & FT_PROPORTIONAL)
866 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
869 for (i=0; i< width; i++ )
870 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
873 fp += BITS_TO_BYTES(width)*r;
877 for (i=0; i< width; i++ )
885 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
887 { *(short *)(DATA + VideoOffset) = pa_clut[BG_COLOR]; VideoOffset += PA_BPP; }
892 VideoOffset += PA_BPP * (spacing-width); //for kerning
897 VideoOffset1 += ROWSIZE; y++;
901 VideoOffset1 += ROWSIZE * skip_lines;
907 int gr_internal_string5m(int x, int y, char *s )
910 ubyte * text_ptr, * next_row, * text_ptr1;
911 int r, BitMask, i, bits, width, spacing, letter, underline;
914 unsigned int VideoOffset, VideoOffset1;
917 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
921 while (next_row != NULL )
923 text_ptr1 = next_row;
926 if (x==0x8000) { //centered
927 int xx = get_centered_x(text_ptr1);
928 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
931 for (r=0; r<FHEIGHT; r++)
934 text_ptr = text_ptr1;
936 VideoOffset = VideoOffset1;
940 if (*text_ptr == '\n' )
942 next_row = &text_ptr[1];
946 if (*text_ptr == CC_COLOR) {
947 FG_COLOR = *(text_ptr+1);
952 if (*text_ptr == CC_LSPACING) {
953 skip_lines = *(text_ptr+1) - '0';
959 if (*text_ptr == CC_UNDERLINE )
961 if ((r==FBASELINE+2) || (r==FBASELINE+3))
966 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
968 letter = *text_ptr-FMINCHAR;
970 if (!INFONT(letter)) { //not in font, draw as space
971 VideoOffset += spacing * PA_BPP;
976 if (FFLAGS & FT_PROPORTIONAL)
979 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
982 for (i=0; i< width; i++ )
983 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
986 fp += BITS_TO_BYTES(width)*r;
990 for (i=0; i< width; i++ )
998 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
1000 VideoOffset += PA_BPP;
1006 VideoOffset += PA_BPP * (spacing-width);
1009 VideoOffset1 += ROWSIZE; y++;
1012 VideoOffset1 += ROWSIZE * skip_lines;
1020 //a bitmap for the character
1021 grs_bitmap char_bm = {
1024 BM_FLAG_TRANSPARENT, //flags
1027 #ifdef BITMAP_SELECTOR
1034 int gr_internal_color_string(int x, int y, char *s )
1037 ubyte * text_ptr, * next_row, * text_ptr1;
1038 int width, spacing,letter;
1041 char_bm.bm_h = FHEIGHT; //set height for chars of this font
1048 while (next_row != NULL)
1050 text_ptr1 = next_row;
1053 text_ptr = text_ptr1;
1057 if (xx==0x8000) //centered
1058 xx = get_centered_x(text_ptr);
1062 if (*text_ptr == '\n' )
1064 next_row = &text_ptr[1];
1069 letter = *text_ptr-FMINCHAR;
1071 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1073 if (!INFONT(letter)) { //not in font, draw as space
1079 if (FFLAGS & FT_PROPORTIONAL)
1080 fp = FCHARS[letter];
1082 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1084 gr_init_bitmap (&char_bm, BM_LINEAR, 0, 0, width, FHEIGHT, width, fp);
1085 gr_bitmapm(xx,yy,&char_bm);
1097 #include "../main/inferno.h"
1098 #include "ogl_init.h"
1100 //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
1102 int pow2ize(int x);//from ogl.c
1104 int get_font_total_width(grs_font * font){
1105 if (font->ft_flags & FT_PROPORTIONAL){
1106 int i,w=0,c=font->ft_minchar;
1107 for (i=0;c<=font->ft_maxchar;i++,c++){
1108 if (font->ft_widths[i]<0)
1110 w+=font->ft_widths[i];
1114 return font->ft_w*(font->ft_maxchar-font->ft_minchar+1);
1117 void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){
1118 int nchars = font->ft_maxchar-font->ft_minchar+1;
1119 int r,x,y,nc=0,smallest=999999,smallr=-1,tries;
1120 int smallprop=10000;
1122 for (h=32;h<=256;h*=2){
1123 // h=pow2ize(font->ft_h*rows+gap*(rows-1));
1124 if (font->ft_h>h)continue;
1125 r=(h/(font->ft_h+gap));
1126 w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r);
1132 mprintf((0,"failed to fit (%ix%i, %ic)\n",w,h,nc));
1137 while(y+font->ft_h<=h){
1142 if (font->ft_flags & FT_PROPORTIONAL){
1143 if (x+font->ft_widths[nc]+gap>w)break;
1144 x+=font->ft_widths[nc++]+gap;
1146 if (x+font->ft_w+gap>w)break;
1160 mprintf((0,"fit: %ix%i %i tries\n",w,h,tries));
1162 if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32)
1183 Error("couldn't fit font?\n");
1184 mprintf((0,"using %ix%i\n",*rw,*rh));
1188 void ogl_init_font(grs_font * font){
1189 int nchars = font->ft_maxchar-font->ft_minchar+1;
1190 int i,w,h,tw,th,x,y,curx=0,cury=0;
1192 // char data[32*32*4];
1194 int gap=0;//having a gap just wastes ram, since we don't filter text textures at all.
1196 ogl_font_choose_size(font,gap,&tw,&th);
1197 data=d_malloc(tw*th);
1198 gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data);
1200 font->ft_parent_bitmap.gltexture=ogl_get_free_texture();
1202 font->ft_bitmaps=(grs_bitmap*)d_malloc( nchars * sizeof(grs_bitmap));
1203 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));
1208 for(i=0;i<nchars;i++){
1209 // s[0]=font->ft_minchar+i;
1210 // gr_get_string_size(s,&w,&h,&aw);
1211 if (font->ft_flags & FT_PROPORTIONAL)
1212 w=font->ft_widths[i];
1215 // mprintf((0,"char %i(%ix%i): ",i,w,h));
1217 mprintf((0,"grr\n"));continue;
1224 Error("font doesn't really fit (%i/%i)?\n",i,nchars);
1225 if (font->ft_flags & FT_COLOR) {
1226 if (font->ft_flags & FT_PROPORTIONAL)
1227 fp = font->ft_chars[i];
1229 fp = font->ft_data + i * w*h;
1232 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w];
1235 // gr_init_bitmap(&font->ft_bitmaps[i],BM_LINEAR,0,0,w,h,w,font->);
1237 int BitMask,bits=0,white=gr_find_closest_color(63,63,63);
1238 // if (w*h>sizeof(data))
1239 // Error("ogl_init_font: toobig\n");
1240 if (font->ft_flags & FT_PROPORTIONAL)
1241 fp = font->ft_chars[i];
1243 fp = font->ft_data + i * BITS_TO_BYTES(w)*h;
1246 for (x=0; x< w; x++ )
1254 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white;
1256 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255;
1261 gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h);
1265 if (!(font->ft_flags & FT_COLOR)) {
1266 //use GL_INTENSITY instead of GL_RGB
1267 if (ogl_intensity4_ok){
1268 font->ft_parent_bitmap.gltexture->internalformat=GL_INTENSITY4;
1269 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE;
1270 }else if (ogl_luminance4_alpha4_ok){
1271 font->ft_parent_bitmap.gltexture->internalformat=GL_LUMINANCE4_ALPHA4;
1272 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE_ALPHA;
1273 }else if (ogl_rgba2_ok){
1274 font->ft_parent_bitmap.gltexture->internalformat=GL_RGBA2;
1275 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1277 font->ft_parent_bitmap.gltexture->internalformat=ogl_rgba_format;
1278 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1281 ogl_loadbmtexture_m(&font->ft_parent_bitmap,0);
1284 int ogl_internal_string(int x, int y, char *s )
1286 ubyte * text_ptr, * next_row, * text_ptr1;
1287 int width, spacing,letter;
1289 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
1295 if (grd_curscreen->sc_canvas.cv_bitmap.bm_type != BM_OGL)
1297 while (next_row != NULL)
1299 text_ptr1 = next_row;
1302 text_ptr = text_ptr1;
1306 if (xx==0x8000) //centered
1307 xx = get_centered_x(text_ptr);
1311 if (*text_ptr == '\n' )
1313 next_row = &text_ptr[1];
1318 letter = *text_ptr-FMINCHAR;
1320 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1322 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
1323 CHECK_EMBEDDED_COLORS() else{
1330 // ogl_ubitblt(FONT->ft_bitmaps[letter].bm_w,FONT->ft_bitmaps[letter].bm_h,xx,yy,0,0,&FONT->ft_bitmaps[letter],NULL);
1331 // if (*text_ptr>='0' && *text_ptr<='9'){
1332 if (FFLAGS&FT_COLOR)
1333 gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);
1335 if (grd_curcanv->cv_bitmap.bm_type==BM_OGL)
1336 ogl_ubitmapm_c(xx,yy,&FONT->ft_bitmaps[letter],FG_COLOR);
1338 Error("ogl_internal_string: non-color string to non-ogl dest\n");
1339 // gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);//ignores color..
1352 int gr_internal_color_string(int x, int y, char *s ){
1353 return ogl_internal_string(x,y,s);
1357 int gr_string(int x, int y, char *s )
1362 Assert(FONT != NULL);
1364 if ( x == 0x8000 ) {
1365 if ( y<0 ) clipped |= 1;
1366 gr_get_string_size(s, &w, &h, &aw );
1367 // for x, since this will be centered, only look at
1369 if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1370 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1372 if ( (y+h) < 0 ) clipped |= 2;
1373 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1376 if ( (x<0) || (y<0) ) clipped |= 1;
1377 gr_get_string_size(s, &w, &h, &aw );
1378 if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1379 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1380 if ( (x+w) < 0 ) clipped |= 2;
1381 if ( (y+h) < 0 ) clipped |= 2;
1382 if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;
1383 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1387 return gr_ustring(x, y, s );
1389 if ( clipped & 2 ) {
1390 // Completely clipped...
1391 mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
1395 if ( clipped & 1 ) {
1396 // Partially clipped...
1397 //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
1400 // Partially clipped...
1403 return ogl_internal_string(x,y,s);
1406 if (FFLAGS & FT_COLOR)
1407 return gr_internal_color_string( x, y, s);
1409 if ( BG_COLOR == -1)
1410 return gr_internal_string_clipped_m( x, y, s );
1412 return gr_internal_string_clipped( x, y, s );
1415 int gr_ustring(int x, int y, char *s )
1419 return ogl_internal_string(x,y,s);
1422 if (FFLAGS & FT_COLOR) {
1424 return gr_internal_color_string(x,y,s);
1431 if ( BG_COLOR == -1)
1432 return gr_internal_string0m(x,y,s);
1434 return gr_internal_string0(x,y,s);
1435 #ifdef __ENV_MSDOS__
1437 if ( BG_COLOR == -1)
1438 return gr_internal_string2m(x,y,s);
1440 return gr_internal_string2(x,y,s);
1441 #endif // __ENV_MSDOS__
1442 #if defined(POLY_ACC)
1444 if ( BG_COLOR == -1)
1445 return gr_internal_string5m(x,y,s);
1447 return gr_internal_string5(x,y,s);
1455 void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width )
1457 int i = 0, longest_width = 0;
1460 *string_height = FHEIGHT;
1462 *average_width = FWIDTH;
1469 // if (*s == CC_UNDERLINE)
1474 *string_height += FHEIGHT;
1480 // 1 = next byte specifies color, so skip the 1 and the color value
1483 else if (*s == CC_LSPACING) {
1484 *string_height += *(s+1)-'0';
1487 get_char_width(s[0],s[1],&width,&spacing);
1488 *string_width += spacing;
1489 if (*string_width > longest_width)
1490 longest_width = *string_width;
1496 *string_width = longest_width;
1500 int gr_uprintf( int x, int y, char * format, ... )
1505 va_start(args, format );
1506 vsprintf(buffer,format,args);
1507 return gr_ustring( x, y, buffer );
1510 int gr_printf( int x, int y, char * format, ... )
1515 va_start(args, format );
1516 vsprintf(buffer,format,args);
1517 return gr_string( x, y, buffer );
1520 void gr_close_font( grs_font * font )
1527 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=font;fontnum++);
1528 Assert(fontnum<MAX_OPEN_FONTS); //did we find slot?
1530 open_font[fontnum].ptr = NULL;
1532 if ( font->ft_chars )
1533 d_free( font->ft_chars );
1534 // d_free( font->oldfont );
1536 if (font->ft_bitmaps)
1537 d_free( font->ft_bitmaps );
1538 gr_free_bitmap_data(&font->ft_parent_bitmap);
1539 // ogl_freebmtexture(&font->ft_parent_bitmap);
1546 //remap (by re-reading) all the color fonts
1547 void gr_remap_color_fonts()
1551 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1554 font = open_font[fontnum].ptr;
1556 if (font && (font->ft_flags & FT_COLOR))
1557 gr_remap_font(font,open_font[fontnum].filename);
1561 void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq );
1562 void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count );
1564 #pragma aux decode_data_asm parm [esi] [ecx] [edi] [ebx] modify exact [esi edi eax ebx ecx] = \
1568 "inc dword ptr [ebx+eax*4]" \
1569 "mov al,[edi+eax]" \
1577 grs_font * gr_init_font( char * fontname )
1579 static int first_time=1;
1582 unsigned char * ptr;
1586 int32_t datasize; //size up to (but not including) palette
1590 for (i=0;i<MAX_OPEN_FONTS;i++)
1591 open_font[i].ptr = NULL;
1595 //find free font slot
1596 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=NULL;fontnum++);
1597 Assert(fontnum<MAX_OPEN_FONTS); //did we find one?
1599 strncpy(open_font[fontnum].filename,fontname,FILENAME_LEN);
1601 fontfile = cfopen(fontname, "rb");
1604 Error( "Can't open font file %s", fontname );
1606 file_id = cfile_read_int(fontfile);
1607 datasize = cfile_read_int(fontfile);
1609 if (file_id != 0x4e465350) /* 'NFSP' */
1610 Error( "File %s is not a font file", fontname );
1612 font = (grs_font *) d_malloc(datasize);
1614 open_font[fontnum].ptr = font;
1616 cfread(font,1,datasize,fontfile);
1619 // gotta translate those endian things
1621 font->ft_w = SWAPSHORT(font->ft_w);
1622 font->ft_h = SWAPSHORT(font->ft_h);
1623 font->ft_flags = SWAPSHORT(font->ft_flags);
1624 font->ft_bytewidth = SWAPSHORT(font->ft_bytewidth);
1625 font->ft_data = (ubyte *)SWAPINT((int)(font->ft_data));
1626 font->ft_chars = (ubyte **)SWAPINT((int)(font->ft_chars));
1627 font->ft_widths = (short *)SWAPINT((int)(font->ft_widths));
1628 font->ft_kerndata = (ubyte *)SWAPINT((int)(font->ft_kerndata));
1631 nchars = font->ft_maxchar-font->ft_minchar+1;
1633 if (font->ft_flags & FT_PROPORTIONAL) {
1635 font->ft_widths = (short *) (((int) font->ft_widths) + ((ubyte *) font));
1638 for (i = 0; i < nchars; i++)
1639 font->ft_widths[i] = SWAPSHORT(font->ft_widths[i]);
1642 font->ft_data = ((int) font->ft_data) + ((ubyte *) font);
1644 font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1646 ptr = font->ft_data;
1648 for (i=0; i< nchars; i++ ) {
1649 font->ft_chars[i] = ptr;
1650 if (font->ft_flags & FT_COLOR)
1651 ptr += font->ft_widths[i] * font->ft_h;
1653 ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1658 font->ft_data = ((unsigned char *) font) + sizeof(*font);
1660 font->ft_chars = NULL;
1661 font->ft_widths = NULL;
1663 ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1666 if (font->ft_flags & FT_KERNED)
1667 font->ft_kerndata = ((int) font->ft_kerndata) + ((ubyte *) font);
1670 if (font->ft_flags & FT_COLOR) { //remap palette
1671 ubyte palette[256*3];
1672 ubyte colormap[256];
1675 cfread(palette,3,256,fontfile); //read the palette
1677 #ifdef MACINTOSH // swap the first and last palette entries (black and white)
1682 for (i = 0; i < 3; i++) {
1684 palette[i] = palette[765+i];
1688 // we also need to swap the data entries as well. black is white and white is black
1690 for (i = 0; i < ptr-font->ft_data; i++) {
1691 if (font->ft_data[i] == 0)
1692 font->ft_data[i] = 255;
1693 else if (font->ft_data[i] == 255)
1694 font->ft_data[i] = 0;
1700 build_colormap_good( (ubyte *)&palette, colormap, freq );
1702 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // chaged from colormap[255] = 255 to this for macintosh
1704 decode_data_asm(font->ft_data, ptr-font->ft_data, colormap, freq );
1717 ogl_init_font(font);
1724 //remap a font by re-reading its data & palette
1725 void gr_remap_font( grs_font *font, char * fontname )
1731 int32_t datasize; //size up to (but not including) palette
1732 int data_ofs,data_len;
1734 if (! (font->ft_flags & FT_COLOR))
1737 fontfile = cfopen(fontname, "rb");
1740 Error( "Can't open font file %s", fontname );
1742 file_id = cfile_read_int(fontfile);
1743 datasize = cfile_read_int(fontfile);
1745 if (file_id != 0x4e465350) /* 'NFSP' */
1746 Error( "File %s is not a font file", fontname );
1748 nchars = font->ft_maxchar-font->ft_minchar+1;
1750 //compute data length
1752 if (font->ft_flags & FT_PROPORTIONAL) {
1754 for (i=0; i< nchars; i++ ) {
1755 if (font->ft_flags & FT_COLOR)
1756 data_len += font->ft_widths[i] * font->ft_h;
1758 data_len += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1762 data_len = nchars * font->ft_w * font->ft_h;
1764 data_ofs = font->ft_data - ((ubyte *) font);
1766 cfseek(fontfile,data_ofs,SEEK_CUR);
1767 cfread(font->ft_data,1,data_len,fontfile); //read raw data
1769 if (font->ft_flags & FT_COLOR) { //remap palette
1770 ubyte palette[256*3];
1771 ubyte colormap[256];
1774 cfseek(fontfile,-sizeof(palette),SEEK_END);
1776 cfread(palette,3,256,fontfile); //read the palette
1778 #ifdef MACINTOSH // swap the first and last palette entries (black and white)
1783 for (i = 0; i < 3; i++) {
1785 palette[i] = palette[765+i];
1789 // we also need to swap the data entries as well. black is white and white is black
1791 for (i = 0; i < data_len; i++) {
1792 if (font->ft_data[i] == 0)
1793 font->ft_data[i] = 255;
1794 else if (font->ft_data[i] == 255)
1795 font->ft_data[i] = 0;
1801 build_colormap_good( (ubyte *)&palette, colormap, freq );
1803 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255;
1805 decode_data_asm(font->ft_data, data_len, colormap, freq );
1814 void gr_set_fontcolor( int fg, int bg )
1820 void gr_set_curfont( grs_font * new )
1826 int gr_internal_string_clipped(int x, int y, char *s )
1829 char * text_ptr, * next_row, * text_ptr1;
1830 int r, BitMask, i, bits, width, spacing, letter, underline;
1837 while (next_row != NULL )
1839 text_ptr1 = next_row;
1843 if (x==0x8000) //centered
1844 x = get_centered_x(text_ptr1);
1848 for (r=0; r<FHEIGHT; r++) {
1849 text_ptr = text_ptr1;
1853 if (*text_ptr == '\n' ) {
1854 next_row = &text_ptr[1];
1858 if (*text_ptr == CC_COLOR) {
1859 FG_COLOR = *(text_ptr+1);
1864 if (*text_ptr == CC_LSPACING) {
1865 Int3(); // Warning: skip lines not supported for clipped strings.
1871 if (*text_ptr == CC_UNDERLINE ) {
1872 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1877 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1879 letter = *text_ptr-FMINCHAR;
1881 if (!INFONT(letter)) { //not in font, draw as space
1887 if (FFLAGS & FT_PROPORTIONAL)
1888 fp = FCHARS[letter];
1890 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1893 for (i=0; i< width; i++ ) {
1894 gr_setcolor(FG_COLOR);
1898 fp += BITS_TO_BYTES(width)*r;
1902 for (i=0; i< width; i++ ) {
1908 gr_setcolor(FG_COLOR);
1910 gr_setcolor(BG_COLOR);
1916 x += spacing-width; //for kerning
1926 int gr_internal_string_clipped_m(int x, int y, char *s )
1929 char * text_ptr, * next_row, * text_ptr1;
1930 int r, BitMask, i, bits, width, spacing, letter, underline;
1937 while (next_row != NULL )
1939 text_ptr1 = next_row;
1943 if (x==0x8000) //centered
1944 x = get_centered_x(text_ptr1);
1948 for (r=0; r<FHEIGHT; r++) {
1951 text_ptr = text_ptr1;
1954 if (*text_ptr == '\n' ) {
1955 next_row = &text_ptr[1];
1959 if (*text_ptr == CC_COLOR) {
1960 FG_COLOR = *(text_ptr+1);
1965 if (*text_ptr == CC_LSPACING) {
1966 Int3(); // Warning: skip lines not supported for clipped strings.
1972 if (*text_ptr == CC_UNDERLINE ) {
1973 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1978 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1980 letter = *text_ptr-FMINCHAR;
1982 if (!INFONT(letter)) { //not in font, draw as space
1988 if (FFLAGS & FT_PROPORTIONAL)
1989 fp = FCHARS[letter];
1991 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1994 for (i=0; i< width; i++ ) {
1995 gr_setcolor(FG_COLOR);
1999 fp += BITS_TO_BYTES(width)*r;
2003 for (i=0; i< width; i++ ) {
2008 if (bits & BitMask) {
2009 gr_setcolor(FG_COLOR);
2018 x += spacing-width; //for kerning