1 /* $Id: font.c,v 1.27 2004-05-15 16:25:35 schaffner Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
17 * Graphical routines for drawing fonts.
35 #include "pa_enabl.h" //$$POLY_ACC
53 #define MAX_OPEN_FONTS 50
54 #define FILENAME_LEN 13
56 typedef struct openfont {
57 char filename[FILENAME_LEN];
62 //list of open fonts, for use (for now) for palette remapping
63 openfont open_font[MAX_OPEN_FONTS];
65 #define FONT grd_curcanv->cv_font
66 #define FG_COLOR grd_curcanv->cv_font_fg_color
67 #define BG_COLOR grd_curcanv->cv_font_bg_color
68 #define FWIDTH FONT->ft_w
69 #define FHEIGHT FONT->ft_h
70 #define FBASELINE FONT->ft_baseline
71 #define FFLAGS FONT->ft_flags
72 #define FMINCHAR FONT->ft_minchar
73 #define FMAXCHAR FONT->ft_maxchar
74 #define FDATA FONT->ft_data
75 #define FCHARS FONT->ft_chars
76 #define FWIDTHS FONT->ft_widths
78 #define BITS_TO_BYTES(x) (((x)+7)>>3)
80 int gr_internal_string_clipped(int x, int y, char *s );
81 int gr_internal_string_clipped_m(int x, int y, char *s );
83 ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second)
85 ubyte *p=font->ft_kerndata;
88 if (p[0]==first && p[1]==second)
96 //takes the character AFTER being offset into font
97 #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
99 //takes the character BEFORE being offset into current font
100 void get_char_width(ubyte c,ubyte c2,int *width,int *spacing)
106 if (!INFONT(letter)) { //not in font, draw as space
108 if (FFLAGS & FT_PROPORTIONAL)
115 if (FFLAGS & FT_PROPORTIONAL)
116 *width = FWIDTHS[letter];
122 if (FFLAGS & FT_KERNED) {
125 if (!(c2==0 || c2=='\n')) {
128 letter2 = c2-FMINCHAR;
130 if (INFONT(letter2)) {
132 p = find_kern_entry(FONT,(ubyte)letter,letter2);
141 int get_centered_x(char *s)
145 for (w=0;*s!=0 && *s!='\n';s++) {
149 continue;//skip color codes.
151 get_char_width(s[0],s[1],&w2,&s2);
155 return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
158 //hack to allow color codes to be embedded in strings -MPM
159 //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string.
160 //function must already have orig_color var set (or they could be passed as args...)
161 //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain
162 int gr_message_color_level=1;
163 #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x03)) { \
166 if (gr_message_color_level >= *(text_ptr-1)) \
167 FG_COLOR = *text_ptr - 1; \
171 else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \
172 if (gr_message_color_level >= *text_ptr - 3) \
173 FG_COLOR=orig_color; \
177 int gr_internal_string0(int x, int y, char *s )
180 ubyte * text_ptr, * next_row, * text_ptr1;
181 int r, BitMask, i, bits, width, spacing, letter, underline;
184 unsigned int VideoOffset, VideoOffset1;
188 VideoOffset1 = y * ROWSIZE + x;
192 while (next_row != NULL )
194 text_ptr1 = next_row;
197 if (x==0x8000) { //centered
198 int xx = get_centered_x(text_ptr1);
199 VideoOffset1 = y * ROWSIZE + xx;
202 for (r=0; r<FHEIGHT; r++)
205 text_ptr = text_ptr1;
207 VideoOffset = VideoOffset1;
211 if (*text_ptr == '\n' )
213 next_row = &text_ptr[1];
217 if (*text_ptr == CC_COLOR) {
218 FG_COLOR = *(text_ptr+1);
223 if (*text_ptr == CC_LSPACING) {
224 skip_lines = *(text_ptr+1) - '0';
230 if (*text_ptr == CC_UNDERLINE )
232 if ((r==FBASELINE+2) || (r==FBASELINE+3))
237 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
239 letter = *text_ptr-FMINCHAR;
241 if (!INFONT(letter)) { //not in font, draw as space
242 VideoOffset += spacing;
247 if (FFLAGS & FT_PROPORTIONAL)
250 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
253 for (i=0; i< width; i++ )
254 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
257 fp += BITS_TO_BYTES(width)*r;
261 for (i=0; i< width; i++ )
269 DATA[VideoOffset++] = (unsigned char) FG_COLOR;
271 DATA[VideoOffset++] = (unsigned char) BG_COLOR;
276 VideoOffset += spacing-width; //for kerning
281 VideoOffset1 += ROWSIZE; y++;
285 VideoOffset1 += ROWSIZE * skip_lines;
291 int gr_internal_string0m(int x, int y, char *s )
294 ubyte * text_ptr, * next_row, * text_ptr1;
295 int r, BitMask, i, bits, width, spacing, letter, underline;
298 unsigned int VideoOffset, VideoOffset1;
300 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
304 VideoOffset1 = y * ROWSIZE + x;
308 while (next_row != NULL )
310 text_ptr1 = next_row;
313 if (x==0x8000) { //centered
314 int xx = get_centered_x(text_ptr1);
315 VideoOffset1 = y * ROWSIZE + xx;
318 for (r=0; r<FHEIGHT; r++)
321 text_ptr = text_ptr1;
323 VideoOffset = VideoOffset1;
327 if (*text_ptr == '\n' )
329 next_row = &text_ptr[1];
333 if (*text_ptr == CC_COLOR) {
334 FG_COLOR = *(text_ptr+1);
339 if (*text_ptr == CC_LSPACING) {
340 skip_lines = *(text_ptr+1) - '0';
346 if (*text_ptr == CC_UNDERLINE )
348 if ((r==FBASELINE+2) || (r==FBASELINE+3))
353 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
355 letter = *text_ptr-FMINCHAR;
357 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
358 CHECK_EMBEDDED_COLORS() else{
359 VideoOffset += spacing;
365 if (FFLAGS & FT_PROPORTIONAL)
368 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
371 for (i=0; i< width; i++ )
372 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
375 fp += BITS_TO_BYTES(width)*r;
379 for (i=0; i< width; i++ )
387 DATA[VideoOffset++] = (unsigned int) FG_COLOR;
395 VideoOffset += spacing-width;
398 VideoOffset1 += ROWSIZE;
402 VideoOffset1 += ROWSIZE * skip_lines;
409 int gr_internal_string2(int x, int y, char *s )
412 ubyte * text_ptr, * next_row, * text_ptr1;
413 int r, BitMask, i, bits, width, spacing, letter, underline;
414 int page_switched, skip_lines = 0;
416 unsigned int VideoOffset, VideoOffset1;
418 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
422 gr_vesa_setpage(VideoOffset1 >> 16);
424 VideoOffset1 &= 0xFFFF;
428 while (next_row != NULL )
430 text_ptr1 = next_row;
433 if (x==0x8000) { //centered
434 int xx = get_centered_x(text_ptr1);
435 VideoOffset1 = y * ROWSIZE + xx;
436 gr_vesa_setpage(VideoOffset1 >> 16);
437 VideoOffset1 &= 0xFFFF;
440 for (r=0; r<FHEIGHT; r++)
442 text_ptr = text_ptr1;
444 VideoOffset = VideoOffset1;
450 if (*text_ptr == '\n' )
452 next_row = &text_ptr[1];
456 if (*text_ptr == CC_COLOR) {
457 FG_COLOR = *(text_ptr+1);
462 if (*text_ptr == CC_LSPACING) {
463 skip_lines = *(text_ptr+1) - '0';
469 if (*text_ptr == CC_UNDERLINE )
471 if ((r==FBASELINE+2) || (r==FBASELINE+3))
476 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
478 Assert(width==spacing); //no kerning support here
480 letter = *text_ptr-FMINCHAR;
482 if (!INFONT(letter)) { //not in font, draw as space
483 VideoOffset += spacing;
488 if (FFLAGS & FT_PROPORTIONAL)
491 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
495 if ( VideoOffset+width > 0xFFFF )
497 for (i=0; i< width; i++ )
499 gr_video_memory[VideoOffset++] = FG_COLOR;
501 if (VideoOffset > 0xFFFF )
503 VideoOffset -= 0xFFFF + 1;
511 for (i=0; i< width; i++ )
512 gr_video_memory[VideoOffset++] = FG_COLOR;
521 fp += BITS_TO_BYTES(width)*r;
525 if ( VideoOffset+width > 0xFFFF )
527 for (i=0; i< width; i++ )
535 gr_video_memory[VideoOffset++] = FG_COLOR;
537 gr_video_memory[VideoOffset++] = BG_COLOR;
541 if (VideoOffset > 0xFFFF )
543 VideoOffset -= 0xFFFF + 1;
555 if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR;
556 else gr_video_memory[VideoOffset+0] = BG_COLOR;
558 if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR;
559 else gr_video_memory[VideoOffset+1] = BG_COLOR;
561 if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR;
562 else gr_video_memory[VideoOffset+2] = BG_COLOR;
564 if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR;
565 else gr_video_memory[VideoOffset+3] = BG_COLOR;
567 if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR;
568 else gr_video_memory[VideoOffset+4] = BG_COLOR;
570 if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR;
571 else gr_video_memory[VideoOffset+5] = BG_COLOR;
573 if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR;
574 else gr_video_memory[VideoOffset+6] = BG_COLOR;
576 if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR;
577 else gr_video_memory[VideoOffset+7] = BG_COLOR;
581 for (i=0; i< width/2 ; i++ )
589 gr_video_memory[VideoOffset++] = FG_COLOR;
591 gr_video_memory[VideoOffset++] = BG_COLOR;
603 gr_video_memory[VideoOffset++] = FG_COLOR;
605 gr_video_memory[VideoOffset++] = BG_COLOR;
615 VideoOffset1 += ROWSIZE;
617 if (VideoOffset1 > 0xFFFF ) {
618 VideoOffset1 -= 0xFFFF + 1;
625 VideoOffset1 += ROWSIZE * skip_lines;
631 int gr_internal_string2m(int x, int y, char *s )
634 char * text_ptr, * next_row, * text_ptr1;
635 int r, BitMask, i, bits, width, spacing, letter, underline;
636 int page_switched, skip_lines = 0;
638 unsigned int VideoOffset, VideoOffset1;
640 VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
642 gr_vesa_setpage(VideoOffset1 >> 16);
644 VideoOffset1 &= 0xFFFF;
648 while (next_row != NULL )
650 text_ptr1 = next_row;
653 if (x==0x8000) { //centered
654 int xx = get_centered_x(text_ptr1);
655 VideoOffset1 = y * ROWSIZE + xx;
656 gr_vesa_setpage(VideoOffset1 >> 16);
657 VideoOffset1 &= 0xFFFF;
660 for (r=0; r<FHEIGHT; r++)
662 text_ptr = text_ptr1;
664 VideoOffset = VideoOffset1;
670 if (*text_ptr == '\n' )
672 next_row = &text_ptr[1];
676 if (*text_ptr == CC_COLOR) {
677 FG_COLOR = *(text_ptr+1);
682 if (*text_ptr == CC_LSPACING) {
683 skip_lines = *(text_ptr+1) - '0';
689 if (*text_ptr == CC_UNDERLINE )
691 if ((r==FBASELINE+2) || (r==FBASELINE+3))
696 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
698 letter = *text_ptr-FMINCHAR;
700 if (!INFONT(letter)) { //not in font, draw as space
701 VideoOffset += width;
706 if (FFLAGS & FT_PROPORTIONAL)
709 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
713 if ( VideoOffset+width > 0xFFFF )
715 for (i=0; i< width; i++ )
717 gr_video_memory[VideoOffset++] = FG_COLOR;
719 if (VideoOffset > 0xFFFF )
721 VideoOffset -= 0xFFFF + 1;
729 for (i=0; i< width; i++ )
730 gr_video_memory[VideoOffset++] = FG_COLOR;
735 fp += BITS_TO_BYTES(width)*r;
739 if ( VideoOffset+width > 0xFFFF )
741 for (i=0; i< width; i++ )
749 gr_video_memory[VideoOffset++] = FG_COLOR;
755 if (VideoOffset > 0xFFFF )
757 VideoOffset -= 0xFFFF + 1;
764 for (i=0; i< width; i++ )
772 gr_video_memory[VideoOffset++] = FG_COLOR;
781 VideoOffset += spacing-width;
785 VideoOffset1 += ROWSIZE;
787 if (VideoOffset1 > 0xFFFF ) {
788 VideoOffset1 -= 0xFFFF + 1;
795 VideoOffset1 += ROWSIZE * skip_lines;
803 #if defined(POLY_ACC)
804 int gr_internal_string5(int x, int y, char *s )
807 ubyte * text_ptr, * next_row, * text_ptr1;
808 int r, BitMask, i, bits, width, spacing, letter, underline;
811 unsigned int VideoOffset, VideoOffset1;
814 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
818 while (next_row != NULL )
820 text_ptr1 = next_row;
823 if (x==0x8000) { //centered
824 int xx = get_centered_x(text_ptr1);
825 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
828 for (r=0; r<FHEIGHT; r++)
831 text_ptr = text_ptr1;
833 VideoOffset = VideoOffset1;
837 if (*text_ptr == '\n' )
839 next_row = &text_ptr[1];
843 if (*text_ptr == CC_COLOR) {
844 FG_COLOR = *(text_ptr+1);
849 if (*text_ptr == CC_LSPACING) {
850 skip_lines = *(text_ptr+1) - '0';
856 if (*text_ptr == CC_UNDERLINE )
858 if ((r==FBASELINE+2) || (r==FBASELINE+3))
863 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
865 letter = *text_ptr-FMINCHAR;
867 if (!INFONT(letter)) { //not in font, draw as space
868 VideoOffset += spacing * PA_BPP;
873 if (FFLAGS & FT_PROPORTIONAL)
876 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
879 for (i=0; i< width; i++ )
880 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
883 fp += BITS_TO_BYTES(width)*r;
887 for (i=0; i< width; i++ )
895 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
897 { *(short *)(DATA + VideoOffset) = pa_clut[BG_COLOR]; VideoOffset += PA_BPP; }
902 VideoOffset += PA_BPP * (spacing-width); //for kerning
907 VideoOffset1 += ROWSIZE; y++;
911 VideoOffset1 += ROWSIZE * skip_lines;
917 int gr_internal_string5m(int x, int y, char *s )
920 ubyte * text_ptr, * next_row, * text_ptr1;
921 int r, BitMask, i, bits, width, spacing, letter, underline;
924 unsigned int VideoOffset, VideoOffset1;
927 VideoOffset1 = y * ROWSIZE + x * PA_BPP;
931 while (next_row != NULL )
933 text_ptr1 = next_row;
936 if (x==0x8000) { //centered
937 int xx = get_centered_x(text_ptr1);
938 VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
941 for (r=0; r<FHEIGHT; r++)
944 text_ptr = text_ptr1;
946 VideoOffset = VideoOffset1;
950 if (*text_ptr == '\n' )
952 next_row = &text_ptr[1];
956 if (*text_ptr == CC_COLOR) {
957 FG_COLOR = *(text_ptr+1);
962 if (*text_ptr == CC_LSPACING) {
963 skip_lines = *(text_ptr+1) - '0';
969 if (*text_ptr == CC_UNDERLINE )
971 if ((r==FBASELINE+2) || (r==FBASELINE+3))
976 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
978 letter = *text_ptr-FMINCHAR;
980 if (!INFONT(letter)) { //not in font, draw as space
981 VideoOffset += spacing * PA_BPP;
986 if (FFLAGS & FT_PROPORTIONAL)
989 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
992 for (i=0; i< width; i++ )
993 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
996 fp += BITS_TO_BYTES(width)*r;
1000 for (i=0; i< width; i++ )
1008 { *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
1010 VideoOffset += PA_BPP;
1016 VideoOffset += PA_BPP * (spacing-width);
1019 VideoOffset1 += ROWSIZE; y++;
1022 VideoOffset1 += ROWSIZE * skip_lines;
1030 //a bitmap for the character
1031 grs_bitmap char_bm = {
1034 BM_FLAG_TRANSPARENT, //flags
1037 #ifdef BITMAP_SELECTOR
1044 int gr_internal_color_string(int x, int y, char *s )
1047 ubyte * text_ptr, * next_row, * text_ptr1;
1048 int width, spacing,letter;
1051 char_bm.bm_h = FHEIGHT; //set height for chars of this font
1058 while (next_row != NULL)
1060 text_ptr1 = next_row;
1063 text_ptr = text_ptr1;
1067 if (xx==0x8000) //centered
1068 xx = get_centered_x(text_ptr);
1072 if (*text_ptr == '\n' )
1074 next_row = &text_ptr[1];
1079 letter = *text_ptr-FMINCHAR;
1081 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1083 if (!INFONT(letter)) { //not in font, draw as space
1089 if (FFLAGS & FT_PROPORTIONAL)
1090 fp = FCHARS[letter];
1092 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1094 gr_init_bitmap (&char_bm, BM_LINEAR, 0, 0, width, FHEIGHT, width, fp);
1095 gr_bitmapm(xx,yy,&char_bm);
1108 #include "ogl_init.h"
1110 //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
1112 int pow2ize(int x);//from ogl.c
1114 int get_font_total_width(grs_font * font){
1115 if (font->ft_flags & FT_PROPORTIONAL){
1116 int i,w=0,c=font->ft_minchar;
1117 for (i=0;c<=font->ft_maxchar;i++,c++){
1118 if (font->ft_widths[i]<0)
1120 w+=font->ft_widths[i];
1124 return font->ft_w*(font->ft_maxchar-font->ft_minchar+1);
1127 void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){
1128 int nchars = font->ft_maxchar-font->ft_minchar+1;
1129 int r,x,y,nc=0,smallest=999999,smallr=-1,tries;
1130 int smallprop=10000;
1132 for (h=32;h<=256;h*=2){
1133 // h=pow2ize(font->ft_h*rows+gap*(rows-1));
1134 if (font->ft_h>h)continue;
1135 r=(h/(font->ft_h+gap));
1136 w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r);
1142 mprintf((0,"failed to fit (%ix%i, %ic)\n",w,h,nc));
1147 while(y+font->ft_h<=h){
1152 if (font->ft_flags & FT_PROPORTIONAL){
1153 if (x+font->ft_widths[nc]+gap>w)break;
1154 x+=font->ft_widths[nc++]+gap;
1156 if (x+font->ft_w+gap>w)break;
1170 mprintf((0,"fit: %ix%i %i tries\n",w,h,tries));
1172 if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32)
1193 Error("couldn't fit font?\n");
1194 mprintf((0,"using %ix%i\n",*rw,*rh));
1198 void ogl_init_font(grs_font * font){
1199 int nchars = font->ft_maxchar-font->ft_minchar+1;
1200 int i,w,h,tw,th,x,y,curx=0,cury=0;
1202 // char data[32*32*4];
1204 int gap=0;//having a gap just wastes ram, since we don't filter text textures at all.
1206 ogl_font_choose_size(font,gap,&tw,&th);
1207 data=d_malloc(tw*th);
1208 gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data);
1210 font->ft_parent_bitmap.gltexture=ogl_get_free_texture();
1212 font->ft_bitmaps=(grs_bitmap*)d_malloc( nchars * sizeof(grs_bitmap));
1213 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));
1218 for(i=0;i<nchars;i++){
1219 // s[0]=font->ft_minchar+i;
1220 // gr_get_string_size(s,&w,&h,&aw);
1221 if (font->ft_flags & FT_PROPORTIONAL)
1222 w=font->ft_widths[i];
1225 // mprintf((0,"char %i(%ix%i): ",i,w,h));
1227 mprintf((0,"grr\n"));continue;
1234 Error("font doesn't really fit (%i/%i)?\n",i,nchars);
1235 if (font->ft_flags & FT_COLOR) {
1236 if (font->ft_flags & FT_PROPORTIONAL)
1237 fp = font->ft_chars[i];
1239 fp = font->ft_data + i * w*h;
1242 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w];
1245 // gr_init_bitmap(&font->ft_bitmaps[i],BM_LINEAR,0,0,w,h,w,font->);
1247 int BitMask,bits=0,white=gr_find_closest_color(63,63,63);
1248 // if (w*h>sizeof(data))
1249 // Error("ogl_init_font: toobig\n");
1250 if (font->ft_flags & FT_PROPORTIONAL)
1251 fp = font->ft_chars[i];
1253 fp = font->ft_data + i * BITS_TO_BYTES(w)*h;
1256 for (x=0; x< w; x++ )
1264 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white;
1266 font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255;
1271 gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h);
1275 if (!(font->ft_flags & FT_COLOR)) {
1276 //use GL_INTENSITY instead of GL_RGB
1277 if (ogl_intensity4_ok){
1278 font->ft_parent_bitmap.gltexture->internalformat=GL_INTENSITY4;
1279 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE;
1280 }else if (ogl_luminance4_alpha4_ok){
1281 font->ft_parent_bitmap.gltexture->internalformat=GL_LUMINANCE4_ALPHA4;
1282 font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE_ALPHA;
1283 }else if (ogl_rgba2_ok){
1284 font->ft_parent_bitmap.gltexture->internalformat=GL_RGBA2;
1285 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1287 font->ft_parent_bitmap.gltexture->internalformat=ogl_rgba_format;
1288 font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1291 ogl_loadbmtexture_m(&font->ft_parent_bitmap,0);
1294 int ogl_internal_string(int x, int y, char *s )
1296 ubyte * text_ptr, * next_row, * text_ptr1;
1297 int width, spacing,letter;
1299 int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
1305 if (grd_curscreen->sc_canvas.cv_bitmap.bm_type != BM_OGL)
1307 while (next_row != NULL)
1309 text_ptr1 = next_row;
1312 text_ptr = text_ptr1;
1316 if (xx==0x8000) //centered
1317 xx = get_centered_x(text_ptr);
1321 if (*text_ptr == '\n' )
1323 next_row = &text_ptr[1];
1328 letter = *text_ptr-FMINCHAR;
1330 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1332 if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space
1333 CHECK_EMBEDDED_COLORS() else{
1340 // ogl_ubitblt(FONT->ft_bitmaps[letter].bm_w,FONT->ft_bitmaps[letter].bm_h,xx,yy,0,0,&FONT->ft_bitmaps[letter],NULL);
1341 // if (*text_ptr>='0' && *text_ptr<='9'){
1342 if (FFLAGS&FT_COLOR)
1343 //gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);
1344 gr_bitmapm(xx,yy,&FONT->ft_bitmaps[letter]); // credits need clipping
1346 if (grd_curcanv->cv_bitmap.bm_type==BM_OGL)
1347 ogl_ubitmapm_c(xx,yy,&FONT->ft_bitmaps[letter],FG_COLOR);
1349 Error("ogl_internal_string: non-color string to non-ogl dest\n");
1350 // gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);//ignores color..
1363 int gr_internal_color_string(int x, int y, char *s ){
1364 return ogl_internal_string(x,y,s);
1368 int gr_string(int x, int y, char *s )
1373 Assert(FONT != NULL);
1375 if ( x == 0x8000 ) {
1376 if ( y<0 ) clipped |= 1;
1377 gr_get_string_size(s, &w, &h, &aw );
1378 // for x, since this will be centered, only look at
1380 if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1381 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1383 if ( (y+h) < 0 ) clipped |= 2;
1384 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1387 if ( (x<0) || (y<0) ) clipped |= 1;
1388 gr_get_string_size(s, &w, &h, &aw );
1389 if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1390 if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1391 if ( (x+w) < 0 ) clipped |= 2;
1392 if ( (y+h) < 0 ) clipped |= 2;
1393 if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;
1394 if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1398 return gr_ustring(x, y, s );
1400 if ( clipped & 2 ) {
1401 // Completely clipped...
1402 mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
1406 if ( clipped & 1 ) {
1407 // Partially clipped...
1408 //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
1411 // Partially clipped...
1414 return ogl_internal_string(x,y,s);
1417 if (FFLAGS & FT_COLOR)
1418 return gr_internal_color_string( x, y, s);
1420 if ( BG_COLOR == -1)
1421 return gr_internal_string_clipped_m( x, y, s );
1423 return gr_internal_string_clipped( x, y, s );
1426 int gr_ustring(int x, int y, char *s )
1430 return ogl_internal_string(x,y,s);
1433 if (FFLAGS & FT_COLOR) {
1435 return gr_internal_color_string(x,y,s);
1442 if ( BG_COLOR == -1)
1443 return gr_internal_string0m(x,y,s);
1445 return gr_internal_string0(x,y,s);
1448 if ( BG_COLOR == -1)
1449 return gr_internal_string2m(x,y,s);
1451 return gr_internal_string2(x,y,s);
1453 #if defined(POLY_ACC)
1455 if ( BG_COLOR == -1)
1456 return gr_internal_string5m(x,y,s);
1458 return gr_internal_string5(x,y,s);
1465 void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width )
1467 int i = 0, longest_width = 0;
1470 *string_height = FHEIGHT;
1472 *average_width = FWIDTH;
1479 // if (*s == CC_UNDERLINE)
1484 *string_height += FHEIGHT;
1490 // 1 = next byte specifies color, so skip the 1 and the color value
1493 else if (*s == CC_LSPACING) {
1494 *string_height += *(s+1)-'0';
1497 get_char_width(s[0],s[1],&width,&spacing);
1499 *string_width += spacing;
1501 if (*string_width > longest_width)
1502 longest_width = *string_width;
1509 *string_width = longest_width;
1513 int gr_uprintf( int x, int y, char * format, ... )
1518 va_start(args, format );
1519 vsprintf(buffer,format,args);
1520 return gr_ustring( x, y, buffer );
1523 int gr_printf( int x, int y, char * format, ... )
1528 va_start(args, format );
1529 vsprintf(buffer,format,args);
1530 return gr_string( x, y, buffer );
1533 void gr_close_font( grs_font * font )
1541 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=font;fontnum++);
1542 Assert(fontnum<MAX_OPEN_FONTS); //did we find slot?
1544 font_data = open_font[fontnum].dataptr;
1545 d_free( font_data );
1547 open_font[fontnum].ptr = NULL;
1548 open_font[fontnum].dataptr = NULL;
1550 if ( font->ft_chars )
1551 d_free( font->ft_chars );
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);
1564 //remap (by re-reading) all the color fonts
1565 void gr_remap_color_fonts()
1569 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1572 font = open_font[fontnum].ptr;
1574 if (font && (font->ft_flags & FT_COLOR))
1575 gr_remap_font(font, open_font[fontnum].filename, open_font[fontnum].dataptr);
1579 void gr_remap_mono_fonts()
1582 con_printf (CON_DEBUG, "gr_remap_mono_fonts ()\n");
1583 for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1585 font = open_font[fontnum].ptr;
1586 if (font && !(font->ft_flags & FT_COLOR))
1587 gr_remap_font(font, open_font[fontnum].filename, open_font[fontnum].dataptr);
1592 #define grs_font_read(gf, fp) cfread(gf, GRS_FONT_SIZE, 1, fp)
1595 * reads a grs_font structure from a CFILE
1597 void grs_font_read(grs_font *gf, CFILE *fp)
1599 gf->ft_w = cfile_read_short(fp);
1600 gf->ft_h = cfile_read_short(fp);
1601 gf->ft_flags = cfile_read_short(fp);
1602 gf->ft_baseline = cfile_read_short(fp);
1603 gf->ft_minchar = cfile_read_byte(fp);
1604 gf->ft_maxchar = cfile_read_byte(fp);
1605 gf->ft_bytewidth = cfile_read_short(fp);
1606 gf->ft_data = (ubyte *)cfile_read_int(fp);
1607 gf->ft_chars = (ubyte **)cfile_read_int(fp);
1608 gf->ft_widths = (short *)cfile_read_int(fp);
1609 gf->ft_kerndata = (ubyte *)cfile_read_int(fp);
1613 grs_font * gr_init_font( char * fontname )
1615 static int first_time=1;
1619 unsigned char * ptr;
1623 int datasize; //size up to (but not including) palette
1627 for (i=0;i<MAX_OPEN_FONTS;i++)
1628 open_font[i].ptr = NULL;
1629 open_font[i].dataptr = NULL;
1633 //find free font slot
1634 for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=NULL;fontnum++);
1635 Assert(fontnum<MAX_OPEN_FONTS); //did we find one?
1637 strncpy(open_font[fontnum].filename,fontname,FILENAME_LEN);
1639 fontfile = cfopen(fontname, "rb");
1642 con_printf(CON_VERBOSE, "Can't open font file %s\n", fontname);
1646 cfread(file_id, 4, 1, fontfile);
1647 if ( !strncmp( file_id, "NFSP", 4 ) ) {
1648 con_printf(CON_NORMAL, "File %s is not a font file\n", fontname );
1652 datasize = cfile_read_int(fontfile);
1653 datasize -= GRS_FONT_SIZE; // subtract the size of the header.
1655 MALLOC(font, grs_font, sizeof(grs_font));
1656 grs_font_read(font, fontfile);
1658 MALLOC(font_data, char, datasize);
1659 cfread(font_data, 1, datasize, fontfile);
1661 open_font[fontnum].ptr = font;
1662 open_font[fontnum].dataptr = font_data;
1664 // make these offsets relative to font_data
1665 font->ft_data = (ubyte *)((int)font->ft_data - GRS_FONT_SIZE);
1666 font->ft_widths = (short *)((int)font->ft_widths - GRS_FONT_SIZE);
1667 font->ft_kerndata = (ubyte *)((int)font->ft_kerndata - GRS_FONT_SIZE);
1669 nchars = font->ft_maxchar - font->ft_minchar + 1;
1671 if (font->ft_flags & FT_PROPORTIONAL) {
1673 font->ft_widths = (short *) &font_data[(int)font->ft_widths];
1674 font->ft_data = &font_data[(int)font->ft_data];
1675 font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1677 ptr = font->ft_data;
1679 for (i=0; i< nchars; i++ ) {
1680 font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]);
1681 font->ft_chars[i] = ptr;
1682 if (font->ft_flags & FT_COLOR)
1683 ptr += font->ft_widths[i] * font->ft_h;
1685 ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1690 font->ft_data = font_data;
1691 font->ft_chars = NULL;
1692 font->ft_widths = NULL;
1694 ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1697 if (font->ft_flags & FT_KERNED)
1698 font->ft_kerndata = &font_data[(int)font->ft_kerndata];
1700 if (font->ft_flags & FT_COLOR) { //remap palette
1701 ubyte palette[256*3];
1702 ubyte colormap[256];
1705 cfread(palette,3,256,fontfile); //read the palette
1707 #ifdef SWAP_0_255 // swap the first and last palette entries (black and white)
1712 for (i = 0; i < 3; i++) {
1714 palette[i] = palette[765+i];
1718 // we also need to swap the data entries as well. black is white and white is black
1720 for (i = 0; i < ptr-font->ft_data; i++) {
1721 if (font->ft_data[i] == 0)
1722 font->ft_data[i] = 255;
1723 else if (font->ft_data[i] == 255)
1724 font->ft_data[i] = 0;
1730 build_colormap_good( (ubyte *)&palette, colormap, freq );
1732 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255 to this for macintosh
1734 decode_data_asm(font->ft_data, ptr - font->ft_data, colormap, freq );
1748 char tests[]="abcdefghij1234.A";
1749 gr_get_string_size(tests,&x,&y,&aw);
1750 // newfont->ft_aw=x/(float)strlen(tests);
1754 ogl_init_font(font);
1761 //remap a font by re-reading its data & palette
1762 void gr_remap_font( grs_font *font, char * fontname, char *font_data )
1768 int datasize; //size up to (but not including) palette
1771 if (! (font->ft_flags & FT_COLOR))
1774 fontfile = cfopen(fontname, "rb");
1777 Error( "Can't open font file %s", fontname );
1779 cfread(file_id, 4, 1, fontfile);
1780 if ( !strncmp( file_id, "NFSP", 4 ) )
1781 Error( "File %s is not a font file", fontname );
1783 datasize = cfile_read_int(fontfile);
1784 datasize -= GRS_FONT_SIZE; // subtract the size of the header.
1786 d_free(font->ft_chars);
1787 grs_font_read(font, fontfile); // have to reread in case mission hogfile overrides font.
1789 cfread(font_data, 1, datasize, fontfile); //read raw data
1791 // make these offsets relative to font_data
1792 font->ft_data = (ubyte *)((int)font->ft_data - GRS_FONT_SIZE);
1793 font->ft_widths = (short *)((int)font->ft_widths - GRS_FONT_SIZE);
1794 font->ft_kerndata = (ubyte *)((int)font->ft_kerndata - GRS_FONT_SIZE);
1796 nchars = font->ft_maxchar - font->ft_minchar + 1;
1798 if (font->ft_flags & FT_PROPORTIONAL) {
1800 font->ft_widths = (short *) &font_data[(int)font->ft_widths];
1801 font->ft_data = &font_data[(int)font->ft_data];
1802 font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1804 ptr = font->ft_data;
1806 for (i=0; i< nchars; i++ ) {
1807 font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]);
1808 font->ft_chars[i] = ptr;
1809 if (font->ft_flags & FT_COLOR)
1810 ptr += font->ft_widths[i] * font->ft_h;
1812 ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1817 font->ft_data = font_data;
1818 font->ft_chars = NULL;
1819 font->ft_widths = NULL;
1821 ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1824 if (font->ft_flags & FT_KERNED)
1825 font->ft_kerndata = &font_data[(int)font->ft_kerndata];
1827 if (font->ft_flags & FT_COLOR) { //remap palette
1828 ubyte palette[256*3];
1829 ubyte colormap[256];
1832 cfread(palette,3,256,fontfile); //read the palette
1834 #ifdef SWAP_0_255 // swap the first and last palette entries (black and white)
1839 for (i = 0; i < 3; i++) {
1841 palette[i] = palette[765+i];
1845 // we also need to swap the data entries as well. black is white and white is black
1847 for (i = 0; i < ptr-font->ft_data; i++) {
1848 if (font->ft_data[i] == 0)
1849 font->ft_data[i] = 255;
1850 else if (font->ft_data[i] == 255)
1851 font->ft_data[i] = 0;
1857 build_colormap_good( (ubyte *)&palette, colormap, freq );
1859 colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255 to this for macintosh
1861 decode_data_asm(font->ft_data, ptr - font->ft_data, colormap, freq );
1868 if (font->ft_bitmaps)
1869 d_free( font->ft_bitmaps );
1870 gr_free_bitmap_data(&font->ft_parent_bitmap);
1871 // ogl_freebmtexture(&font->ft_parent_bitmap);
1873 ogl_init_font(font);
1878 void gr_set_fontcolor( int fg, int bg )
1884 void gr_set_curfont( grs_font * new )
1890 int gr_internal_string_clipped(int x, int y, char *s )
1893 char * text_ptr, * next_row, * text_ptr1;
1894 int r, BitMask, i, bits, width, spacing, letter, underline;
1901 while (next_row != NULL )
1903 text_ptr1 = next_row;
1907 if (x==0x8000) //centered
1908 x = get_centered_x(text_ptr1);
1912 for (r=0; r<FHEIGHT; r++) {
1913 text_ptr = text_ptr1;
1917 if (*text_ptr == '\n' ) {
1918 next_row = &text_ptr[1];
1922 if (*text_ptr == CC_COLOR) {
1923 FG_COLOR = *(text_ptr+1);
1928 if (*text_ptr == CC_LSPACING) {
1929 Int3(); // Warning: skip lines not supported for clipped strings.
1935 if (*text_ptr == CC_UNDERLINE ) {
1936 if ((r==FBASELINE+2) || (r==FBASELINE+3))
1941 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1943 letter = *text_ptr-FMINCHAR;
1945 if (!INFONT(letter)) { //not in font, draw as space
1951 if (FFLAGS & FT_PROPORTIONAL)
1952 fp = FCHARS[letter];
1954 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1957 for (i=0; i< width; i++ ) {
1958 gr_setcolor(FG_COLOR);
1962 fp += BITS_TO_BYTES(width)*r;
1966 for (i=0; i< width; i++ ) {
1972 gr_setcolor(FG_COLOR);
1974 gr_setcolor(BG_COLOR);
1980 x += spacing-width; //for kerning
1990 int gr_internal_string_clipped_m(int x, int y, char *s )
1993 char * text_ptr, * next_row, * text_ptr1;
1994 int r, BitMask, i, bits, width, spacing, letter, underline;
2001 while (next_row != NULL )
2003 text_ptr1 = next_row;
2007 if (x==0x8000) //centered
2008 x = get_centered_x(text_ptr1);
2012 for (r=0; r<FHEIGHT; r++) {
2015 text_ptr = text_ptr1;
2018 if (*text_ptr == '\n' ) {
2019 next_row = &text_ptr[1];
2023 if (*text_ptr == CC_COLOR) {
2024 FG_COLOR = *(text_ptr+1);
2029 if (*text_ptr == CC_LSPACING) {
2030 Int3(); // Warning: skip lines not supported for clipped strings.
2036 if (*text_ptr == CC_UNDERLINE ) {
2037 if ((r==FBASELINE+2) || (r==FBASELINE+3))
2042 get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
2044 letter = *text_ptr-FMINCHAR;
2046 if (!INFONT(letter)) { //not in font, draw as space
2052 if (FFLAGS & FT_PROPORTIONAL)
2053 fp = FCHARS[letter];
2055 fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
2058 for (i=0; i< width; i++ ) {
2059 gr_setcolor(FG_COLOR);
2063 fp += BITS_TO_BYTES(width)*r;
2067 for (i=0; i< width; i++ ) {
2072 if (bits & BitMask) {
2073 gr_setcolor(FG_COLOR);
2082 x += spacing-width; //for kerning