1 /* $Id: font.c,v 1.25 2003/03/19 19:21:34 btb Exp $ */
2 /*
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.
13 */
14 
15 /*
16  *
17  * Graphical routines for drawing fonts.
18  *
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include <conf.h>
23 #endif
24 
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include <fcntl.h>
31 #include <unistd.h>
32 
33 #include "pa_enabl.h"                   //$$POLY_ACC
34 #include "u_mem.h"
35 
36 #include "gr.h"
37 #include "grdef.h"
38 #include "error.h"
39 
40 #include "cfile.h"
41 #include "mono.h"
42 #include "byteswap.h"
43 #include "bitmap.h"
44 
45 #if defined(POLY_ACC)
46 #include "poly_acc.h"
47 #endif
48 
49 #include "makesig.h"
50 
51 #define MAX_OPEN_FONTS	50
52 #define FILENAME_LEN		13
53 
54 typedef struct openfont {
55 	char filename[FILENAME_LEN];
56 	grs_font *ptr;
57 	char *dataptr;
58 } openfont;
59 
60 //list of open fonts, for use (for now) for palette remapping
61 openfont open_font[MAX_OPEN_FONTS];
62 
63 #define FONT        grd_curcanv->cv_font
64 #define FG_COLOR    grd_curcanv->cv_font_fg_color
65 #define BG_COLOR    grd_curcanv->cv_font_bg_color
66 #define FWIDTH       FONT->ft_w
67 #define FHEIGHT      FONT->ft_h
68 #define FBASELINE    FONT->ft_baseline
69 #define FFLAGS       FONT->ft_flags
70 #define FMINCHAR     FONT->ft_minchar
71 #define FMAXCHAR     FONT->ft_maxchar
72 #define FDATA        FONT->ft_data
73 #define FCHARS       FONT->ft_chars
74 #define FWIDTHS      FONT->ft_widths
75 
76 #define BITS_TO_BYTES(x)    (((x)+7)>>3)
77 
78 int gr_internal_string_clipped(int x, int y, char *s );
79 int gr_internal_string_clipped_m(int x, int y, char *s );
80 
find_kern_entry(grs_font * font,ubyte first,ubyte second)81 ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second)
82 {
83 	ubyte *p=font->ft_kerndata;
84 
85 	while (*p!=255)
86 		if (p[0]==first && p[1]==second)
87 			return p;
88 		else p+=3;
89 
90 	return NULL;
91 
92 }
93 
94 //takes the character AFTER being offset into font
95 #define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR))
96 
97 //takes the character BEFORE being offset into current font
get_char_width(ubyte c,ubyte c2,int * width,int * spacing)98 void get_char_width(ubyte c,ubyte c2,int *width,int *spacing)
99 {
100 	int letter;
101 
102 	letter = c-FMINCHAR;
103 
104 	if (!INFONT(letter)) {				//not in font, draw as space
105 		*width=0;
106 		if (FFLAGS & FT_PROPORTIONAL)
107 			*spacing = FWIDTH/2;
108 		else
109 			*spacing = FWIDTH;
110 		return;
111 	}
112 
113 	if (FFLAGS & FT_PROPORTIONAL)
114 		*width = FWIDTHS[letter];
115 	else
116 		*width = FWIDTH;
117 
118 	*spacing = *width;
119 
120 	if (FFLAGS & FT_KERNED)  {
121 		ubyte *p;
122 
123 		if (!(c2==0 || c2=='\n')) {
124 			int letter2;
125 
126 			letter2 = c2-FMINCHAR;
127 
128 			if (INFONT(letter2)) {
129 
130 				p = find_kern_entry(FONT,(ubyte)letter,letter2);
131 
132 				if (p)
133 					*spacing = p[2];
134 			}
135 		}
136 	}
137 }
138 
get_centered_x(char * s)139 int get_centered_x(char *s)
140 {
141 	int w,w2,s2;
142 
143 	for (w=0;*s!=0 && *s!='\n';s++) {
144 		if (*s<=0x06) {
145 			if (*s<=0x03)
146 				s++;
147 			continue;//skip color codes.
148 		}
149 		get_char_width(s[0],s[1],&w2,&s2);
150 		w += s2;
151 	}
152 
153 	return ((grd_curcanv->cv_bitmap.bm_w - w) / 2);
154 }
155 
156 //hack to allow color codes to be embedded in strings -MPM
157 //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string.
158 //function must already have orig_color var set (or they could be passed as args...)
159 //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain
160 int gr_message_color_level=1;
161 #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x03)) { \
162 		text_ptr++; \
163 		if (*text_ptr){ \
164 			if (gr_message_color_level >= *(text_ptr-1)) \
165 				FG_COLOR = *text_ptr - 1; \
166 			text_ptr++; \
167 		} \
168 	} \
169 	else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \
170 		if (gr_message_color_level >= *text_ptr - 3) \
171 			FG_COLOR=orig_color; \
172 		text_ptr++; \
173 	}
174 
gr_internal_string0(int x,int y,char * s)175 int gr_internal_string0(int x, int y, char *s )
176 {
177 	unsigned char * fp;
178 	ubyte * text_ptr, * next_row, * text_ptr1;
179 	int r, BitMask, i, bits, width, spacing, letter, underline;
180 	int	skip_lines = 0;
181 
182 	unsigned int VideoOffset, VideoOffset1;
183 
184         bits=0;
185 
186 	VideoOffset1 = y * ROWSIZE + x;
187 
188 	next_row = s;
189 
190 	while (next_row != NULL )
191 	{
192 		text_ptr1 = next_row;
193 		next_row = NULL;
194 
195 		if (x==0x8000) {			//centered
196 			int xx = get_centered_x(text_ptr1);
197 			VideoOffset1 = y * ROWSIZE + xx;
198 		}
199 
200 		for (r=0; r<FHEIGHT; r++)
201 		{
202 
203 			text_ptr = text_ptr1;
204 
205 			VideoOffset = VideoOffset1;
206 
207 			while (*text_ptr)
208 			{
209 				if (*text_ptr == '\n' )
210 				{
211 					next_row = &text_ptr[1];
212 					break;
213 				}
214 
215 				if (*text_ptr == CC_COLOR) {
216 					FG_COLOR = *(text_ptr+1);
217 					text_ptr += 2;
218 					continue;
219 				}
220 
221 				if (*text_ptr == CC_LSPACING) {
222 					skip_lines = *(text_ptr+1) - '0';
223 					text_ptr += 2;
224 					continue;
225 				}
226 
227 				underline = 0;
228 				if (*text_ptr == CC_UNDERLINE )
229 				{
230 					if ((r==FBASELINE+2) || (r==FBASELINE+3))
231 						underline = 1;
232 					text_ptr++;
233 				}
234 
235 				get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
236 
237 				letter = *text_ptr-FMINCHAR;
238 
239 				if (!INFONT(letter)) {	//not in font, draw as space
240 					VideoOffset += spacing;
241 					text_ptr++;
242 					continue;
243 				}
244 
245 				if (FFLAGS & FT_PROPORTIONAL)
246 					fp = FCHARS[letter];
247 				else
248 					fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
249 
250 				if (underline)
251 					for (i=0; i< width; i++ )
252 						DATA[VideoOffset++] = (unsigned char) FG_COLOR;
253 				else
254 				{
255 					fp += BITS_TO_BYTES(width)*r;
256 
257 					BitMask = 0;
258 
259 					for (i=0; i< width; i++ )
260 					{
261 						if (BitMask==0) {
262 							bits = *fp++;
263 							BitMask = 0x80;
264 						}
265 
266 						if (bits & BitMask)
267 							DATA[VideoOffset++] = (unsigned char) FG_COLOR;
268 						else
269 							DATA[VideoOffset++] = (unsigned char) BG_COLOR;
270 						BitMask >>= 1;
271 					}
272 				}
273 
274 				VideoOffset += spacing-width;		//for kerning
275 
276 				text_ptr++;
277 			}
278 
279 			VideoOffset1 += ROWSIZE; y++;
280 		}
281 
282 		y += skip_lines;
283 		VideoOffset1 += ROWSIZE * skip_lines;
284 		skip_lines = 0;
285 	}
286 	return 0;
287 }
288 
gr_internal_string0m(int x,int y,char * s)289 int gr_internal_string0m(int x, int y, char *s )
290 {
291 	unsigned char * fp;
292 	ubyte * text_ptr, * next_row, * text_ptr1;
293 	int r, BitMask, i, bits, width, spacing, letter, underline;
294 	int	skip_lines = 0;
295 
296 	unsigned int VideoOffset, VideoOffset1;
297 
298 	int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
299 
300         bits=0;
301 
302 	VideoOffset1 = y * ROWSIZE + x;
303 
304 	next_row = s;
305 
306 	while (next_row != NULL )
307 	{
308 		text_ptr1 = next_row;
309 		next_row = NULL;
310 
311 		if (x==0x8000) {			//centered
312 			int xx = get_centered_x(text_ptr1);
313 			VideoOffset1 = y * ROWSIZE + xx;
314 		}
315 
316 		for (r=0; r<FHEIGHT; r++)
317 		{
318 
319 			text_ptr = text_ptr1;
320 
321 			VideoOffset = VideoOffset1;
322 
323 			while (*text_ptr)
324 			{
325 				if (*text_ptr == '\n' )
326 				{
327 					next_row = &text_ptr[1];
328 					break;
329 				}
330 
331 				if (*text_ptr == CC_COLOR) {
332 					FG_COLOR = *(text_ptr+1);
333 					text_ptr += 2;
334 					continue;
335 				}
336 
337 				if (*text_ptr == CC_LSPACING) {
338 					skip_lines = *(text_ptr+1) - '0';
339 					text_ptr += 2;
340 					continue;
341 				}
342 
343 				underline = 0;
344 				if (*text_ptr == CC_UNDERLINE )
345 				{
346 					if ((r==FBASELINE+2) || (r==FBASELINE+3))
347 						underline = 1;
348 					text_ptr++;
349 				}
350 
351 				get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
352 
353 				letter = *text_ptr-FMINCHAR;
354 
355 				if (!INFONT(letter) || *text_ptr<=0x06) {	//not in font, draw as space
356 					CHECK_EMBEDDED_COLORS() else{
357 						VideoOffset += spacing;
358 						text_ptr++;
359 					}
360 					continue;
361 				}
362 
363 				if (FFLAGS & FT_PROPORTIONAL)
364 					fp = FCHARS[letter];
365 				else
366 					fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
367 
368 				if (underline)
369 					for (i=0; i< width; i++ )
370 						DATA[VideoOffset++] = (unsigned int) FG_COLOR;
371 				else
372 				{
373 					fp += BITS_TO_BYTES(width)*r;
374 
375 					BitMask = 0;
376 
377 					for (i=0; i< width; i++ )
378 					{
379 						if (BitMask==0) {
380 							bits = *fp++;
381 							BitMask = 0x80;
382 						}
383 
384 						if (bits & BitMask)
385 							DATA[VideoOffset++] = (unsigned int) FG_COLOR;
386 						else
387 							VideoOffset++;
388 						BitMask >>= 1;
389 					}
390 				}
391 				text_ptr++;
392 
393 				VideoOffset += spacing-width;
394 			}
395 
396 			VideoOffset1 += ROWSIZE;
397 			y++;
398 		}
399 		y += skip_lines;
400 		VideoOffset1 += ROWSIZE * skip_lines;
401 		skip_lines = 0;
402 	}
403 	return 0;
404 }
405 
406 #ifdef __MSDOS__
gr_internal_string2(int x,int y,char * s)407 int gr_internal_string2(int x, int y, char *s )
408 {
409 	unsigned char * fp;
410 	ubyte * text_ptr, * next_row, * text_ptr1;
411 	int r, BitMask, i, bits, width, spacing, letter, underline;
412 	int page_switched, skip_lines = 0;
413 
414 	unsigned int VideoOffset, VideoOffset1;
415 
416 	VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
417 
418 	bits = 0;
419 
420 	gr_vesa_setpage(VideoOffset1 >> 16);
421 
422 	VideoOffset1 &= 0xFFFF;
423 
424 	next_row = s;
425 
426 	while (next_row != NULL )
427 	{
428 		text_ptr1 = next_row;
429 		next_row = NULL;
430 
431 		if (x==0x8000) {			//centered
432 			int xx = get_centered_x(text_ptr1);
433 			VideoOffset1 = y * ROWSIZE + xx;
434 			gr_vesa_setpage(VideoOffset1 >> 16);
435 			VideoOffset1 &= 0xFFFF;
436 		}
437 
438 		for (r=0; r<FHEIGHT; r++)
439 		{
440 			text_ptr = text_ptr1;
441 
442 			VideoOffset = VideoOffset1;
443 
444 			page_switched = 0;
445 
446 			while (*text_ptr)
447 			{
448 				if (*text_ptr == '\n' )
449 				{
450 					next_row = &text_ptr[1];
451 					break;
452 				}
453 
454 				if (*text_ptr == CC_COLOR) {
455 					FG_COLOR = *(text_ptr+1);
456 					text_ptr += 2;
457 					continue;
458 				}
459 
460 				if (*text_ptr == CC_LSPACING) {
461 					skip_lines = *(text_ptr+1) - '0';
462 					text_ptr += 2;
463 					continue;
464 				}
465 
466 				underline = 0;
467 				if (*text_ptr == CC_UNDERLINE )
468 				{
469 					if ((r==FBASELINE+2) || (r==FBASELINE+3))
470 						underline = 1;
471 					text_ptr++;
472 				}
473 
474 				get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
475 
476 				Assert(width==spacing);		//no kerning support here
477 
478 				letter = *text_ptr-FMINCHAR;
479 
480 				if (!INFONT(letter)) {	//not in font, draw as space
481 					VideoOffset += spacing;
482 					text_ptr++;
483 					continue;
484 				}
485 
486 				if (FFLAGS & FT_PROPORTIONAL)
487 					fp = FCHARS[letter];
488 				else
489 					fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
490 
491 				if (underline)
492 				{
493 					if ( VideoOffset+width > 0xFFFF )
494 					{
495 						for (i=0; i< width; i++ )
496 						{
497 							gr_video_memory[VideoOffset++] = FG_COLOR;
498 
499 							if (VideoOffset > 0xFFFF )
500 							{
501 								VideoOffset -= 0xFFFF + 1;
502 								page_switched = 1;
503 								gr_vesa_incpage();
504 							}
505 						}
506 					}
507 					else
508 					{
509 						for (i=0; i< width; i++ )
510 							gr_video_memory[VideoOffset++] = FG_COLOR;
511 					}
512 				}
513 				else
514 				{
515 					// fp -- dword
516 					// VideoOffset
517 					// width
518 
519 					fp += BITS_TO_BYTES(width)*r;
520 
521 					BitMask = 0;
522 
523 					if ( VideoOffset+width > 0xFFFF )
524 					{
525 						for (i=0; i< width; i++ )
526 						{
527 							if (BitMask==0) {
528 								bits = *fp++;
529 								BitMask = 0x80;
530 							}
531 
532 							if (bits & BitMask)
533 								gr_video_memory[VideoOffset++] = FG_COLOR;
534 							else
535 								gr_video_memory[VideoOffset++] = BG_COLOR;
536 
537 							BitMask >>= 1;
538 
539 							if (VideoOffset > 0xFFFF )
540 							{
541 								VideoOffset -= 0xFFFF + 1;
542 								page_switched = 1;
543 								gr_vesa_incpage();
544 							}
545 
546 						}
547 					} else {
548 
549 						if (width == 8 )
550 						{
551 							bits = *fp++;
552 
553 							if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR;
554 							else gr_video_memory[VideoOffset+0] = BG_COLOR;
555 
556 							if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR;
557 							else gr_video_memory[VideoOffset+1] = BG_COLOR;
558 
559 							if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR;
560 							else gr_video_memory[VideoOffset+2] = BG_COLOR;
561 
562 							if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR;
563 							else gr_video_memory[VideoOffset+3] = BG_COLOR;
564 
565 							if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR;
566 							else gr_video_memory[VideoOffset+4] = BG_COLOR;
567 
568 							if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR;
569 							else gr_video_memory[VideoOffset+5] = BG_COLOR;
570 
571 							if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR;
572 							else gr_video_memory[VideoOffset+6] = BG_COLOR;
573 
574 							if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR;
575 							else gr_video_memory[VideoOffset+7] = BG_COLOR;
576 
577 							VideoOffset += 8;
578 						} else {
579 							for (i=0; i< width/2 ; i++ )
580 							{
581 								if (BitMask==0) {
582 									bits = *fp++;
583 									BitMask = 0x80;
584 								}
585 
586 								if (bits & BitMask)
587 									gr_video_memory[VideoOffset++] = FG_COLOR;
588 								else
589 									gr_video_memory[VideoOffset++] = BG_COLOR;
590 								BitMask >>= 1;
591 
592 
593 								// Unroll twice
594 
595 								if (BitMask==0) {
596 									bits = *fp++;
597 									BitMask = 0x80;
598 								}
599 
600 								if (bits & BitMask)
601 									gr_video_memory[VideoOffset++] = FG_COLOR;
602 								else
603 									gr_video_memory[VideoOffset++] = BG_COLOR;
604 								BitMask >>= 1;
605 							}
606 						}
607 					}
608 				}
609 				text_ptr++;
610 			}
611 
612 			y ++;
613 			VideoOffset1 += ROWSIZE;
614 
615 			if (VideoOffset1 > 0xFFFF ) {
616 				VideoOffset1 -= 0xFFFF + 1;
617 				if (!page_switched)
618 					gr_vesa_incpage();
619 			}
620 		}
621 
622 		y += skip_lines;
623 		VideoOffset1 += ROWSIZE * skip_lines;
624 		skip_lines = 0;
625 	}
626 	return 0;
627 }
628 
gr_internal_string2m(int x,int y,char * s)629 int gr_internal_string2m(int x, int y, char *s )
630 {
631 	unsigned char * fp;
632 	char * text_ptr, * next_row, * text_ptr1;
633 	int r, BitMask, i, bits, width, spacing, letter, underline;
634 	int page_switched, skip_lines = 0;
635 
636 	unsigned int VideoOffset, VideoOffset1;
637 
638 	VideoOffset1 = (size_t)DATA + y * ROWSIZE + x;
639 
640 	gr_vesa_setpage(VideoOffset1 >> 16);
641 
642 	VideoOffset1 &= 0xFFFF;
643 
644 	next_row = s;
645 
646 	while (next_row != NULL )
647 	{
648 		text_ptr1 = next_row;
649 		next_row = NULL;
650 
651 		if (x==0x8000) {			//centered
652 			int xx = get_centered_x(text_ptr1);
653 			VideoOffset1 = y * ROWSIZE + xx;
654 			gr_vesa_setpage(VideoOffset1 >> 16);
655 			VideoOffset1 &= 0xFFFF;
656 		}
657 
658 		for (r=0; r<FHEIGHT; r++)
659 		{
660 			text_ptr = text_ptr1;
661 
662 			VideoOffset = VideoOffset1;
663 
664 			page_switched = 0;
665 
666 			while (*text_ptr)
667 			{
668 				if (*text_ptr == '\n' )
669 				{
670 					next_row = &text_ptr[1];
671 					break;
672 				}
673 
674 				if (*text_ptr == CC_COLOR) {
675 					FG_COLOR = *(text_ptr+1);
676 					text_ptr += 2;
677 					continue;
678 				}
679 
680 				if (*text_ptr == CC_LSPACING) {
681 					skip_lines = *(text_ptr+1) - '0';
682 					text_ptr += 2;
683 					continue;
684 				}
685 
686 				underline = 0;
687 				if (*text_ptr == CC_UNDERLINE )
688 				{
689 					if ((r==FBASELINE+2) || (r==FBASELINE+3))
690 						underline = 1;
691 					text_ptr++;
692 				}
693 
694 				get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
695 
696 				letter = *text_ptr-FMINCHAR;
697 
698 				if (!INFONT(letter)) {	//not in font, draw as space
699 					VideoOffset += width;
700 					text_ptr++;
701 					continue;
702 				}
703 
704 				if (FFLAGS & FT_PROPORTIONAL)
705 					fp = FCHARS[letter];
706 				else
707 					fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
708 
709 				if (underline)
710 				{
711 					if ( VideoOffset+width > 0xFFFF )
712 					{
713 						for (i=0; i< width; i++ )
714 						{
715 							gr_video_memory[VideoOffset++] = FG_COLOR;
716 
717 							if (VideoOffset > 0xFFFF )
718 							{
719 								VideoOffset -= 0xFFFF + 1;
720 								page_switched = 1;
721 								gr_vesa_incpage();
722 							}
723 						}
724 					}
725 					else
726 					{
727 						for (i=0; i< width; i++ )
728 							gr_video_memory[VideoOffset++] = FG_COLOR;
729 					}
730 				}
731 				else
732 				{
733 					fp += BITS_TO_BYTES(width)*r;
734 
735 					BitMask = 0;
736 
737 					if ( VideoOffset+width > 0xFFFF )
738 					{
739 						for (i=0; i< width; i++ )
740 						{
741 							if (BitMask==0) {
742 								bits = *fp++;
743 								BitMask = 0x80;
744 							}
745 
746 							if (bits & BitMask)
747 								gr_video_memory[VideoOffset++] = FG_COLOR;
748 							else
749 								VideoOffset++;
750 
751 							BitMask >>= 1;
752 
753 							if (VideoOffset > 0xFFFF )
754 							{
755 								VideoOffset -= 0xFFFF + 1;
756 								page_switched = 1;
757 								gr_vesa_incpage();
758 							}
759 
760 						}
761 					} else {
762 						for (i=0; i< width; i++ )
763 						{
764 							if (BitMask==0) {
765 								bits = *fp++;
766 								BitMask = 0x80;
767 							}
768 
769 							if (bits & BitMask)
770 								gr_video_memory[VideoOffset++] = FG_COLOR;
771 							else
772 								VideoOffset++;;
773 							BitMask >>= 1;
774 						}
775 					}
776 				}
777 				text_ptr++;
778 
779 				VideoOffset += spacing-width;
780 			}
781 
782 			y ++;
783 			VideoOffset1 += ROWSIZE;
784 
785 			if (VideoOffset1 > 0xFFFF ) {
786 				VideoOffset1 -= 0xFFFF + 1;
787 				if (!page_switched)
788 					gr_vesa_incpage();
789 			}
790 		}
791 
792 		y += skip_lines;
793 		VideoOffset1 += ROWSIZE * skip_lines;
794 		skip_lines = 0;
795 	}
796 	return 0;
797 }
798 
799 #endif // __MSDOS__
800 
801 #if defined(POLY_ACC)
gr_internal_string5(int x,int y,char * s)802 int gr_internal_string5(int x, int y, char *s )
803 {
804 	unsigned char * fp;
805 	ubyte * text_ptr, * next_row, * text_ptr1;
806 	int r, BitMask, i, bits, width, spacing, letter, underline;
807 	int	skip_lines = 0;
808 
809 	unsigned int VideoOffset, VideoOffset1;
810 
811     pa_flush();
812     VideoOffset1 = y * ROWSIZE + x * PA_BPP;
813 
814 	next_row = s;
815 
816 	while (next_row != NULL )
817 	{
818 		text_ptr1 = next_row;
819 		next_row = NULL;
820 
821 		if (x==0x8000) {			//centered
822 			int xx = get_centered_x(text_ptr1);
823             VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
824 		}
825 
826 		for (r=0; r<FHEIGHT; r++)
827 		{
828 
829 			text_ptr = text_ptr1;
830 
831 			VideoOffset = VideoOffset1;
832 
833 			while (*text_ptr)
834 			{
835 				if (*text_ptr == '\n' )
836 				{
837 					next_row = &text_ptr[1];
838 					break;
839 				}
840 
841 				if (*text_ptr == CC_COLOR) {
842 					FG_COLOR = *(text_ptr+1);
843 					text_ptr += 2;
844 					continue;
845 				}
846 
847 				if (*text_ptr == CC_LSPACING) {
848 					skip_lines = *(text_ptr+1) - '0';
849 					text_ptr += 2;
850 					continue;
851 				}
852 
853 				underline = 0;
854 				if (*text_ptr == CC_UNDERLINE )
855 				{
856 					if ((r==FBASELINE+2) || (r==FBASELINE+3))
857 						underline = 1;
858 					text_ptr++;
859 				}
860 
861 				get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
862 
863 				letter = *text_ptr-FMINCHAR;
864 
865 				if (!INFONT(letter)) {	//not in font, draw as space
866                     VideoOffset += spacing * PA_BPP;
867 					text_ptr++;
868 					continue;
869 				}
870 
871 				if (FFLAGS & FT_PROPORTIONAL)
872 					fp = FCHARS[letter];
873 				else
874 					fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
875 
876 				if (underline)
877 					for (i=0; i< width; i++ )
878                     {    *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
879 				else
880 				{
881 					fp += BITS_TO_BYTES(width)*r;
882 
883 					BitMask = 0;
884 
885 					for (i=0; i< width; i++ )
886 					{
887 						if (BitMask==0) {
888 							bits = *fp++;
889 							BitMask = 0x80;
890 						}
891 
892 						if (bits & BitMask)
893                         {    *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
894                         else
895                         {    *(short *)(DATA + VideoOffset) = pa_clut[BG_COLOR]; VideoOffset += PA_BPP; }
896                         BitMask >>= 1;
897 					}
898 				}
899 
900                 VideoOffset += PA_BPP * (spacing-width);       //for kerning
901 
902 				text_ptr++;
903 			}
904 
905 			VideoOffset1 += ROWSIZE; y++;
906 		}
907 
908 		y += skip_lines;
909 		VideoOffset1 += ROWSIZE * skip_lines;
910 		skip_lines = 0;
911 	}
912 	return 0;
913 }
914 
gr_internal_string5m(int x,int y,char * s)915 int gr_internal_string5m(int x, int y, char *s )
916 {
917 	unsigned char * fp;
918 	ubyte * text_ptr, * next_row, * text_ptr1;
919 	int r, BitMask, i, bits, width, spacing, letter, underline;
920 	int	skip_lines = 0;
921 
922 	unsigned int VideoOffset, VideoOffset1;
923 
924     pa_flush();
925     VideoOffset1 = y * ROWSIZE + x * PA_BPP;
926 
927 	next_row = s;
928 
929 	while (next_row != NULL )
930 	{
931 		text_ptr1 = next_row;
932 		next_row = NULL;
933 
934 		if (x==0x8000) {			//centered
935 			int xx = get_centered_x(text_ptr1);
936             VideoOffset1 = y * ROWSIZE + xx * PA_BPP;
937 		}
938 
939 		for (r=0; r<FHEIGHT; r++)
940 		{
941 
942 			text_ptr = text_ptr1;
943 
944 			VideoOffset = VideoOffset1;
945 
946 			while (*text_ptr)
947 			{
948 				if (*text_ptr == '\n' )
949 				{
950 					next_row = &text_ptr[1];
951 					break;
952 				}
953 
954 				if (*text_ptr == CC_COLOR) {
955 					FG_COLOR = *(text_ptr+1);
956 					text_ptr += 2;
957 					continue;
958 				}
959 
960 				if (*text_ptr == CC_LSPACING) {
961 					skip_lines = *(text_ptr+1) - '0';
962 					text_ptr += 2;
963 					continue;
964 				}
965 
966 				underline = 0;
967 				if (*text_ptr == CC_UNDERLINE )
968 				{
969 					if ((r==FBASELINE+2) || (r==FBASELINE+3))
970 						underline = 1;
971 					text_ptr++;
972 				}
973 
974 				get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
975 
976 				letter = *text_ptr-FMINCHAR;
977 
978 				if (!INFONT(letter)) {	//not in font, draw as space
979                     VideoOffset += spacing * PA_BPP;
980 					text_ptr++;
981 					continue;
982 				}
983 
984 				if (FFLAGS & FT_PROPORTIONAL)
985 					fp = FCHARS[letter];
986 				else
987 					fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
988 
989 				if (underline)
990 					for (i=0; i< width; i++ )
991                     {    *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
992                 else
993 				{
994 					fp += BITS_TO_BYTES(width)*r;
995 
996 					BitMask = 0;
997 
998 					for (i=0; i< width; i++ )
999 					{
1000 						if (BitMask==0) {
1001 							bits = *fp++;
1002 							BitMask = 0x80;
1003 						}
1004 
1005 						if (bits & BitMask)
1006                         {    *(short *)(DATA + VideoOffset) = pa_clut[FG_COLOR]; VideoOffset += PA_BPP; }
1007                         else
1008                             VideoOffset += PA_BPP;
1009 						BitMask >>= 1;
1010 					}
1011 				}
1012 				text_ptr++;
1013 
1014                 VideoOffset += PA_BPP * (spacing-width);
1015 			}
1016 
1017 			VideoOffset1 += ROWSIZE; y++;
1018 		}
1019 		y += skip_lines;
1020 		VideoOffset1 += ROWSIZE * skip_lines;
1021 		skip_lines = 0;
1022 	}
1023 	return 0;
1024 }
1025 #endif
1026 
1027 #ifndef OGL
1028 //a bitmap for the character
1029 grs_bitmap char_bm = {
1030 				0,0,0,0,						//x,y,w,h
1031 				BM_LINEAR,					//type
1032 				BM_FLAG_TRANSPARENT,		//flags
1033 				0,								//rowsize
1034 				NULL,							//data
1035 #ifdef BITMAP_SELECTOR
1036 				0,				//selector
1037 #endif
1038 				0,     //avg_color
1039 				0      //unused
1040 };
1041 
gr_internal_color_string(int x,int y,char * s)1042 int gr_internal_color_string(int x, int y, char *s )
1043 {
1044 	unsigned char * fp;
1045 	ubyte * text_ptr, * next_row, * text_ptr1;
1046 	int width, spacing,letter;
1047 	int xx,yy;
1048 
1049 	char_bm.bm_h = FHEIGHT;		//set height for chars of this font
1050 
1051 	next_row = s;
1052 
1053 	yy = y;
1054 
1055 
1056 	while (next_row != NULL)
1057 	{
1058 		text_ptr1 = next_row;
1059 		next_row = NULL;
1060 
1061 		text_ptr = text_ptr1;
1062 
1063 		xx = x;
1064 
1065 		if (xx==0x8000)			//centered
1066 			xx = get_centered_x(text_ptr);
1067 
1068 		while (*text_ptr)
1069 		{
1070 			if (*text_ptr == '\n' )
1071 			{
1072 				next_row = &text_ptr[1];
1073 				yy += FHEIGHT;
1074 				break;
1075 			}
1076 
1077 			letter = *text_ptr-FMINCHAR;
1078 
1079 			get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1080 
1081 			if (!INFONT(letter)) {	//not in font, draw as space
1082 				xx += spacing;
1083 				text_ptr++;
1084 				continue;
1085 			}
1086 
1087 			if (FFLAGS & FT_PROPORTIONAL)
1088 				fp = FCHARS[letter];
1089 			else
1090 				fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1091 
1092 			gr_init_bitmap (&char_bm, BM_LINEAR, 0, 0, width, FHEIGHT, width, fp);
1093 			gr_bitmapm(xx,yy,&char_bm);
1094 
1095 			xx += spacing;
1096 
1097 			text_ptr++;
1098 		}
1099 
1100 	}
1101 	return 0;
1102 }
1103 
1104 #else //OGL
1105 
1106 #include "ogl_init.h"
1107 #include "args.h"
1108 //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
1109 
1110 int pow2ize(int x);//from ogl.c
1111 
get_font_total_width(grs_font * font)1112 int get_font_total_width(grs_font * font){
1113 	if (font->ft_flags & FT_PROPORTIONAL){
1114 		int i,w=0,c=font->ft_minchar;
1115 		for (i=0;c<=font->ft_maxchar;i++,c++){
1116 			if (font->ft_widths[i]<0)
1117 				Error("heh?\n");
1118 			w+=font->ft_widths[i];
1119 		}
1120 		return w;
1121 	}else{
1122 		return font->ft_w*(font->ft_maxchar-font->ft_minchar+1);
1123 	}
1124 }
ogl_font_choose_size(grs_font * font,int gap,int * rw,int * rh)1125 void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){
1126 	int	nchars = font->ft_maxchar-font->ft_minchar+1;
1127 	int r,x,y,nc=0,smallest=999999,smallr=-1,tries;
1128 	int smallprop=10000;
1129 	int h,w;
1130 	for (h=32;h<=256;h*=2){
1131 //		h=pow2ize(font->ft_h*rows+gap*(rows-1));
1132 		if (font->ft_h>h)continue;
1133 		r=(h/(font->ft_h+gap));
1134 		w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r);
1135 		tries=0;
1136 		do {
1137 			if (tries)
1138 				w=pow2ize(w+1);
1139 			if(tries>3){
1140 				mprintf((0,"failed to fit (%ix%i, %ic)\n",w,h,nc));
1141 				break;
1142 			}
1143 			nc=0;
1144 			y=0;
1145 			while(y+font->ft_h<=h){
1146 				x=0;
1147 				while (x<w){
1148 					if (nc==nchars)
1149 						break;
1150 					if (font->ft_flags & FT_PROPORTIONAL){
1151 						if (x+font->ft_widths[nc]+gap>w)break;
1152 						x+=font->ft_widths[nc++]+gap;
1153 					}else{
1154 						if (x+font->ft_w+gap>w)break;
1155 						x+=font->ft_w+gap;
1156 						nc++;
1157 					}
1158 				}
1159 				if (nc==nchars)
1160 					break;
1161 				y+=font->ft_h+gap;
1162 			}
1163 
1164 			tries++;
1165 		}while(nc!=nchars);
1166 		if (nc!=nchars)
1167 			continue;
1168 		mprintf((0,"fit: %ix%i  %i tries\n",w,h,tries));
1169 
1170 		if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32)
1171 			if (w>=h){
1172 				if (w/h<smallprop){
1173 					smallprop=w/h;
1174 					smallest++;//hack
1175 				}
1176 			}else{
1177 				if (h/w<smallprop){
1178 					smallprop=h/w;
1179 					smallest++;//hack
1180 				}
1181 			}
1182 		}
1183 		if (w*h<smallest){
1184 			smallr=1;
1185 			smallest=w*h;
1186 			*rw=w;
1187 			*rh=h;
1188 		}
1189 	}
1190 	if (smallr<=0)
1191 		Error("couldn't fit font?\n");
1192 	mprintf((0,"using %ix%i\n",*rw,*rh));
1193 
1194 }
1195 
ogl_init_font(grs_font * font)1196 void ogl_init_font(grs_font * font){
1197 	int	nchars = font->ft_maxchar-font->ft_minchar+1;
1198 	int i,w,h,tw,th,x,y,curx=0,cury=0;
1199 	char *fp;
1200 	//	char data[32*32*4];
1201 	char *data;
1202 	int gap=0;//having a gap just wastes ram, since we don't filter text textures at all.
1203 	//	char s[2];
1204 	ogl_font_choose_size(font,gap,&tw,&th);
1205 	data=d_malloc(tw*th);
1206 	gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data);
1207 
1208 	font->ft_parent_bitmap.gltexture=ogl_get_free_texture();
1209 
1210 	font->ft_bitmaps=(grs_bitmap*)d_malloc( nchars * sizeof(grs_bitmap));
1211 	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));
1212 	//	s[1]=0;
1213 	h=font->ft_h;
1214 	//	sleep(5);
1215 
1216 	for(i=0;i<nchars;i++){
1217 		//		s[0]=font->ft_minchar+i;
1218 		//		gr_get_string_size(s,&w,&h,&aw);
1219 		if (font->ft_flags & FT_PROPORTIONAL)
1220 			w=font->ft_widths[i];
1221 		else
1222 			w=font->ft_w;
1223 //		mprintf((0,"char %i(%ix%i): ",i,w,h));
1224 		if (w<1 || w>256){
1225 			mprintf((0,"grr\n"));continue;
1226 		}
1227 		if (curx+w+gap>tw){
1228 			cury+=h+gap;
1229 			curx=0;
1230 		}
1231 		if (cury+h>th)
1232 			Error("font doesn't really fit (%i/%i)?\n",i,nchars);
1233 		if (font->ft_flags & FT_COLOR) {
1234 			if (font->ft_flags & FT_PROPORTIONAL)
1235 				fp = font->ft_chars[i];
1236 			else
1237 				fp = font->ft_data + i * w*h;
1238 			for (y=0;y<h;y++)
1239 				for (x=0;x<w;x++){
1240 					font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w];
1241 				}
1242 
1243 			//			gr_init_bitmap(&font->ft_bitmaps[i],BM_LINEAR,0,0,w,h,w,font->);
1244 		}else{
1245 			int BitMask,bits=0,white=gr_find_closest_color(63,63,63);
1246 			//			if (w*h>sizeof(data))
1247 			//				Error("ogl_init_font: toobig\n");
1248 			if (font->ft_flags & FT_PROPORTIONAL)
1249 				fp = font->ft_chars[i];
1250 			else
1251 				fp = font->ft_data + i * BITS_TO_BYTES(w)*h;
1252 			for (y=0;y<h;y++){
1253 				BitMask=0;
1254 				for (x=0; x< w; x++ )
1255 				{
1256 					if (BitMask==0) {
1257 						bits = *fp++;
1258 						BitMask = 0x80;
1259 					}
1260 
1261 					if (bits & BitMask)
1262 						font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white;
1263 					else
1264 						font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255;
1265 					BitMask >>= 1;
1266 				}
1267 			}
1268 		}
1269 		gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h);
1270 
1271 		curx+=w+gap;
1272 	}
1273 	if (!(font->ft_flags & FT_COLOR)) {
1274 		//use GL_INTENSITY instead of GL_RGB
1275 		if (ogl_intensity4_ok){
1276 			font->ft_parent_bitmap.gltexture->internalformat=GL_INTENSITY4;
1277 			font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE;
1278 		}else if (ogl_luminance4_alpha4_ok){
1279 			font->ft_parent_bitmap.gltexture->internalformat=GL_LUMINANCE4_ALPHA4;
1280 			font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE_ALPHA;
1281 		}else if (ogl_rgba2_ok){
1282 			font->ft_parent_bitmap.gltexture->internalformat=GL_RGBA2;
1283 			font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1284 		}else{
1285 			font->ft_parent_bitmap.gltexture->internalformat=ogl_rgba_format;
1286 			font->ft_parent_bitmap.gltexture->format=GL_RGBA;
1287 		}
1288 	}
1289 	ogl_loadbmtexture_m(&font->ft_parent_bitmap,0);
1290 }
1291 
ogl_internal_string(int x,int y,char * s)1292 int ogl_internal_string(int x, int y, char *s )
1293 {
1294 	ubyte * text_ptr, * next_row, * text_ptr1;
1295 	int width, spacing,letter;
1296 	int xx,yy;
1297 	int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM
1298 
1299 	next_row = s;
1300 
1301 	yy = y;
1302 
1303 	if (grd_curscreen->sc_canvas.cv_bitmap.bm_type != BM_OGL)
1304 		Error("carp.\n");
1305 	while (next_row != NULL)
1306 	{
1307 		text_ptr1 = next_row;
1308 		next_row = NULL;
1309 
1310 		text_ptr = text_ptr1;
1311 
1312 		xx = x;
1313 
1314 		if (xx==0x8000)			//centered
1315 			xx = get_centered_x(text_ptr);
1316 
1317 		while (*text_ptr)
1318 		{
1319 			if (*text_ptr == '\n' )
1320 			{
1321 				next_row = &text_ptr[1];
1322 				yy += FHEIGHT;
1323 				break;
1324 			}
1325 
1326 			letter = *text_ptr-FMINCHAR;
1327 
1328 			get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1329 
1330 			if (!INFONT(letter) || *text_ptr<=0x06) {	//not in font, draw as space
1331 				CHECK_EMBEDDED_COLORS() else{
1332 					xx += spacing;
1333 					text_ptr++;
1334 				}
1335 				continue;
1336 			}
1337 
1338 //			ogl_ubitblt(FONT->ft_bitmaps[letter].bm_w,FONT->ft_bitmaps[letter].bm_h,xx,yy,0,0,&FONT->ft_bitmaps[letter],NULL);
1339 //			if (*text_ptr>='0' && *text_ptr<='9'){
1340 			if (FFLAGS&FT_COLOR)
1341 				//gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);
1342 				gr_bitmapm(xx,yy,&FONT->ft_bitmaps[letter]); // credits need clipping
1343 			else{
1344 				if (grd_curcanv->cv_bitmap.bm_type==BM_OGL)
1345 					ogl_ubitmapm_c(xx,yy,&FONT->ft_bitmaps[letter],FG_COLOR);
1346 				else
1347 					Error("ogl_internal_string: non-color string to non-ogl dest\n");
1348 //					gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);//ignores color..
1349 			}
1350 			//}
1351 
1352 			xx += spacing;
1353 
1354 			text_ptr++;
1355 		}
1356 
1357 	}
1358 	return 0;
1359 }
1360 
gr_internal_color_string(int x,int y,char * s)1361 int gr_internal_color_string(int x, int y, char *s ){
1362 	return ogl_internal_string(x,y,s);
1363 }
1364 #endif //OGL
1365 
gr_string(int x,int y,char * s)1366 int gr_string(int x, int y, char *s )
1367 {
1368 	int w, h, aw;
1369 	int clipped=0;
1370 
1371 	Assert(FONT != NULL);
1372 
1373 	if ( x == 0x8000 )	{
1374 		if ( y<0 ) clipped |= 1;
1375 		gr_get_string_size(s, &w, &h, &aw );
1376 		// for x, since this will be centered, only look at
1377 		// width.
1378 		if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1379 		if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1380 
1381 		if ( (y+h) < 0 ) clipped |= 2;
1382 		if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1383 
1384 	} else {
1385 		if ( (x<0) || (y<0) ) clipped |= 1;
1386 		gr_get_string_size(s, &w, &h, &aw );
1387 		if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1;
1388 		if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1;
1389 		if ( (x+w) < 0 ) clipped |= 2;
1390 		if ( (y+h) < 0 ) clipped |= 2;
1391 		if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2;
1392 		if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2;
1393 	}
1394 
1395 	if ( !clipped )
1396 		return gr_ustring(x, y, s );
1397 
1398 	if ( clipped & 2 )	{
1399 		// Completely clipped...
1400 		mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y ));
1401 		return 0;
1402 	}
1403 
1404 	if ( clipped & 1 )	{
1405 		// Partially clipped...
1406 		//mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y ));
1407 	}
1408 
1409 	// Partially clipped...
1410 #ifdef OGL
1411 	if (TYPE==BM_OGL)
1412 		return ogl_internal_string(x,y,s);
1413 #endif
1414 
1415 	if (FFLAGS & FT_COLOR)
1416 		return gr_internal_color_string( x, y, s);
1417 
1418 	if ( BG_COLOR == -1)
1419 		return gr_internal_string_clipped_m( x, y, s );
1420 
1421 	return gr_internal_string_clipped( x, y, s );
1422 }
1423 
gr_ustring(int x,int y,char * s)1424 int gr_ustring(int x, int y, char *s )
1425 {
1426 #ifdef OGL
1427 	if (TYPE==BM_OGL)
1428 		return ogl_internal_string(x,y,s);
1429 #endif
1430 
1431 	if (FFLAGS & FT_COLOR) {
1432 
1433 		return gr_internal_color_string(x,y,s);
1434 
1435 	}
1436 	else
1437 		switch( TYPE )
1438 		{
1439 		case BM_LINEAR:
1440 			if ( BG_COLOR == -1)
1441 				return gr_internal_string0m(x,y,s);
1442 			else
1443 				return gr_internal_string0(x,y,s);
1444 #ifdef __MSDOS__
1445 		case BM_SVGA:
1446 			if ( BG_COLOR == -1)
1447 				return gr_internal_string2m(x,y,s);
1448 			else
1449 				return gr_internal_string2(x,y,s);
1450 #endif // __MSDOS__
1451 #if defined(POLY_ACC)
1452         case BM_LINEAR15:
1453 			if ( BG_COLOR == -1)
1454 				return gr_internal_string5m(x,y,s);
1455 			else
1456 				return gr_internal_string5(x,y,s);
1457 #endif
1458 		}
1459 	return 0;
1460 }
1461 
1462 
gr_get_string_size(char * s,int * string_width,int * string_height,int * average_width)1463 void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width )
1464 {
1465 	int i = 0, longest_width = 0;
1466 	int width,spacing;
1467 
1468 	*string_height = FHEIGHT;
1469 	*string_width = 0;
1470 	*average_width = FWIDTH;
1471 
1472 	if (s != NULL )
1473 	{
1474 		*string_width = 0;
1475 		while (*s)
1476 		{
1477 //			if (*s == CC_UNDERLINE)
1478 //				s++;
1479 			while (*s == '\n')
1480 			{
1481 				s++;
1482 				*string_height += FHEIGHT;
1483 				*string_width = 0;
1484 			}
1485 
1486 			if (*s == 0) break;
1487 
1488 			//	1 = next byte specifies color, so skip the 1 and the color value
1489 			if (*s == CC_COLOR)
1490 				s += 2;
1491 			else if (*s == CC_LSPACING) {
1492 				*string_height += *(s+1)-'0';
1493 				s += 2;
1494 			} else {
1495 				get_char_width(s[0],s[1],&width,&spacing);
1496 
1497 				*string_width += spacing;
1498 
1499 				if (*string_width > longest_width)
1500 					longest_width = *string_width;
1501 
1502 				i++;
1503 				s++;
1504 			}
1505 		}
1506 	}
1507 	*string_width = longest_width;
1508 }
1509 
1510 
gr_uprintf(int x,int y,char * format,...)1511 int gr_uprintf( int x, int y, char * format, ... )
1512 {
1513 	char buffer[1000];
1514 	va_list args;
1515 
1516 	va_start(args, format );
1517 	vsprintf(buffer,format,args);
1518 	return gr_ustring( x, y, buffer );
1519 }
1520 
gr_printf(int x,int y,char * format,...)1521 int gr_printf( int x, int y, char * format, ... )
1522 {
1523 	char buffer[1000];
1524 	va_list args;
1525 
1526 	va_start(args, format );
1527 	vsprintf(buffer,format,args);
1528 	return gr_string( x, y, buffer );
1529 }
1530 
gr_close_font(grs_font * font)1531 void gr_close_font( grs_font * font )
1532 {
1533 	if (font)
1534 	{
1535 		int fontnum;
1536 		char * font_data;
1537 
1538 		//find font in list
1539 		for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=font;fontnum++);
1540 		Assert(fontnum<MAX_OPEN_FONTS);	//did we find slot?
1541 
1542 		font_data = open_font[fontnum].dataptr;
1543 		d_free( font_data );
1544 
1545 		open_font[fontnum].ptr = NULL;
1546 		open_font[fontnum].dataptr = NULL;
1547 
1548 		if ( font->ft_chars )
1549 			d_free( font->ft_chars );
1550 #ifdef OGL
1551 		if (font->ft_bitmaps)
1552 			d_free( font->ft_bitmaps );
1553 		gr_free_bitmap_data(&font->ft_parent_bitmap);
1554 //		ogl_freebmtexture(&font->ft_parent_bitmap);
1555 #endif
1556 		d_free( font );
1557 
1558 
1559 	}
1560 }
1561 
1562 //remap (by re-reading) all the color fonts
gr_remap_color_fonts()1563 void gr_remap_color_fonts()
1564 {
1565 	int fontnum;
1566 
1567 	for (fontnum=0;fontnum<MAX_OPEN_FONTS;fontnum++) {
1568 		grs_font *font;
1569 
1570 		font = open_font[fontnum].ptr;
1571 
1572 		if (font && (font->ft_flags & FT_COLOR))
1573 			gr_remap_font(font, open_font[fontnum].filename, open_font[fontnum].dataptr);
1574 	}
1575 }
1576 
1577 #ifdef FAST_FILE_IO
1578 #define grs_font_read(gf, fp) cfread(gf, GRS_FONT_SIZE, 1, fp)
1579 #else
1580 /*
1581  * reads a grs_font structure from a CFILE
1582  */
grs_font_read(grs_font * gf,CFILE * fp)1583 void grs_font_read(grs_font *gf, CFILE *fp)
1584 {
1585 	gf->ft_w = cfile_read_short(fp);
1586 	gf->ft_h = cfile_read_short(fp);
1587 	gf->ft_flags = cfile_read_short(fp);
1588 	gf->ft_baseline = cfile_read_short(fp);
1589 	gf->ft_minchar = cfile_read_byte(fp);
1590 	gf->ft_maxchar = cfile_read_byte(fp);
1591 	gf->ft_bytewidth = cfile_read_short(fp);
1592 	gf->ft_data = (ubyte *)cfile_read_int(fp);
1593 	gf->ft_chars = (ubyte **)cfile_read_int(fp);
1594 	gf->ft_widths = (short *)cfile_read_int(fp);
1595 	gf->ft_kerndata = (ubyte *)cfile_read_int(fp);
1596 }
1597 #endif
1598 
gr_init_font(char * fontname)1599 grs_font * gr_init_font( char * fontname )
1600 {
1601 	static int first_time=1;
1602 	grs_font *font;
1603 	char *font_data;
1604 	int i,fontnum;
1605 	unsigned char * ptr;
1606 	int nchars;
1607 	CFILE *fontfile;
1608 	char file_id[4];
1609 	int datasize;	//size up to (but not including) palette
1610 
1611 	if (first_time) {
1612 		int i;
1613 		for (i=0;i<MAX_OPEN_FONTS;i++)
1614 			open_font[i].ptr = NULL;
1615 			open_font[i].dataptr = NULL;
1616 		first_time=0;
1617 	}
1618 
1619 	//find free font slot
1620 	for (fontnum=0;fontnum<MAX_OPEN_FONTS && open_font[fontnum].ptr!=NULL;fontnum++);
1621 	Assert(fontnum<MAX_OPEN_FONTS);	//did we find one?
1622 
1623 	strncpy(open_font[fontnum].filename,fontname,FILENAME_LEN);
1624 
1625 	fontfile = cfopen(fontname, "rb");
1626 
1627 	if (!fontfile) {
1628 		con_printf(CON_VERBOSE, "Can't open font file %s\n", fontname);
1629 		return NULL;
1630 	}
1631 
1632 	cfread(file_id, 4, 1, fontfile);
1633 	if ( !strncmp( file_id, "NFSP", 4 ) ) {
1634 		con_printf(CON_NORMAL, "File %s is not a font file\n", fontname );
1635 		return NULL;
1636 	}
1637 
1638 	datasize = cfile_read_int(fontfile);
1639 	datasize -= GRS_FONT_SIZE; // subtract the size of the header.
1640 
1641 	MALLOC(font, grs_font, sizeof(grs_font));
1642 	grs_font_read(font, fontfile);
1643 
1644 	MALLOC(font_data, char, datasize);
1645 	cfread(font_data, 1, datasize, fontfile);
1646 
1647 	open_font[fontnum].ptr = font;
1648 	open_font[fontnum].dataptr = font_data;
1649 
1650 	// make these offsets relative to font_data
1651 	font->ft_data = (ubyte *)((int)font->ft_data - GRS_FONT_SIZE);
1652 	font->ft_widths = (short *)((int)font->ft_widths - GRS_FONT_SIZE);
1653 	font->ft_kerndata = (ubyte *)((int)font->ft_kerndata - GRS_FONT_SIZE);
1654 
1655 	nchars = font->ft_maxchar - font->ft_minchar + 1;
1656 
1657 	if (font->ft_flags & FT_PROPORTIONAL) {
1658 
1659 		font->ft_widths = (short *) &font_data[(int)font->ft_widths];
1660 		font->ft_data = &font_data[(int)font->ft_data];
1661 		font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1662 
1663 		ptr = font->ft_data;
1664 
1665 		for (i=0; i< nchars; i++ ) {
1666 			font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]);
1667 			font->ft_chars[i] = ptr;
1668 			if (font->ft_flags & FT_COLOR)
1669 				ptr += font->ft_widths[i] * font->ft_h;
1670 			else
1671 				ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1672 		}
1673 
1674 	} else  {
1675 
1676 		font->ft_data   = font_data;
1677 		font->ft_chars  = NULL;
1678 		font->ft_widths = NULL;
1679 
1680 		ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1681 	}
1682 
1683 	if (font->ft_flags & FT_KERNED)
1684 		font->ft_kerndata = &font_data[(int)font->ft_kerndata];
1685 
1686 	if (font->ft_flags & FT_COLOR) {		//remap palette
1687 		ubyte palette[256*3];
1688 		ubyte colormap[256];
1689 		int freq[256];
1690 
1691 		cfread(palette,3,256,fontfile);		//read the palette
1692 
1693 #ifdef SWAP_0_255			// swap the first and last palette entries (black and white)
1694 		{
1695 			int i;
1696 			ubyte c;
1697 
1698 			for (i = 0; i < 3; i++) {
1699 				c = palette[i];
1700 				palette[i] = palette[765+i];
1701 				palette[765+i] = c;
1702 			}
1703 
1704 //  we also need to swap the data entries as well.  black is white and white is black
1705 
1706 			for (i = 0; i < ptr-font->ft_data; i++) {
1707 				if (font->ft_data[i] == 0)
1708 					font->ft_data[i] = 255;
1709 				else if (font->ft_data[i] == 255)
1710 					font->ft_data[i] = 0;
1711 			}
1712 
1713 		}
1714 #endif
1715 
1716 		build_colormap_good( (ubyte *)&palette, colormap, freq );
1717 
1718 		colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR;              // changed from colormap[255] = 255 to this for macintosh
1719 
1720 		decode_data_asm(font->ft_data, ptr - font->ft_data, colormap, freq );
1721 
1722 	}
1723 
1724 	cfclose(fontfile);
1725 
1726 	//set curcanv vars
1727 
1728 	FONT        = font;
1729 	FG_COLOR    = 0;
1730 	BG_COLOR    = 0;
1731 
1732 	{
1733 		int x,y,aw;
1734 		char tests[]="abcdefghij1234.A";
1735 		gr_get_string_size(tests,&x,&y,&aw);
1736 //		newfont->ft_aw=x/(float)strlen(tests);
1737 	}
1738 
1739 #ifdef OGL
1740 	ogl_init_font(font);
1741 #endif
1742 
1743 	return font;
1744 
1745 }
1746 
1747 //remap a font by re-reading its data & palette
gr_remap_font(grs_font * font,char * fontname,char * font_data)1748 void gr_remap_font( grs_font *font, char * fontname, char *font_data )
1749 {
1750 	int i;
1751 	int nchars;
1752 	CFILE *fontfile;
1753 	char file_id[4];
1754 	int datasize;        //size up to (but not including) palette
1755 	unsigned char *ptr;
1756 
1757 	if (! (font->ft_flags & FT_COLOR))
1758 		return;
1759 
1760 	fontfile = cfopen(fontname, "rb");
1761 
1762 	if (!fontfile)
1763 		Error( "Can't open font file %s", fontname );
1764 
1765 	cfread(file_id, 4, 1, fontfile);
1766 	if ( !strncmp( file_id, "NFSP", 4 ) )
1767 		Error( "File %s is not a font file", fontname );
1768 
1769 	datasize = cfile_read_int(fontfile);
1770 	datasize -= GRS_FONT_SIZE; // subtract the size of the header.
1771 
1772 	d_free(font->ft_chars);
1773 	grs_font_read(font, fontfile); // have to reread in case mission hogfile overrides font.
1774 
1775 	cfread(font_data, 1, datasize, fontfile);  //read raw data
1776 
1777 	// make these offsets relative to font_data
1778 	font->ft_data = (ubyte *)((int)font->ft_data - GRS_FONT_SIZE);
1779 	font->ft_widths = (short *)((int)font->ft_widths - GRS_FONT_SIZE);
1780 	font->ft_kerndata = (ubyte *)((int)font->ft_kerndata - GRS_FONT_SIZE);
1781 
1782 	nchars = font->ft_maxchar - font->ft_minchar + 1;
1783 
1784 	if (font->ft_flags & FT_PROPORTIONAL) {
1785 
1786 		font->ft_widths = (short *) &font_data[(int)font->ft_widths];
1787 		font->ft_data = &font_data[(int)font->ft_data];
1788 		font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *));
1789 
1790 		ptr = font->ft_data;
1791 
1792 		for (i=0; i< nchars; i++ ) {
1793 			font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]);
1794 			font->ft_chars[i] = ptr;
1795 			if (font->ft_flags & FT_COLOR)
1796 				ptr += font->ft_widths[i] * font->ft_h;
1797 			else
1798 				ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h;
1799 		}
1800 
1801 	} else  {
1802 
1803 		font->ft_data   = font_data;
1804 		font->ft_chars  = NULL;
1805 		font->ft_widths = NULL;
1806 
1807 		ptr = font->ft_data + (nchars * font->ft_w * font->ft_h);
1808 	}
1809 
1810 	if (font->ft_flags & FT_KERNED)
1811 		font->ft_kerndata = &font_data[(int)font->ft_kerndata];
1812 
1813 	if (font->ft_flags & FT_COLOR) {		//remap palette
1814 		ubyte palette[256*3];
1815 		ubyte colormap[256];
1816 		int freq[256];
1817 
1818 		cfread(palette,3,256,fontfile);		//read the palette
1819 
1820 #ifdef SWAP_0_255			// swap the first and last palette entries (black and white)
1821 		{
1822 			int i;
1823 			ubyte c;
1824 
1825 			for (i = 0; i < 3; i++) {
1826 				c = palette[i];
1827 				palette[i] = palette[765+i];
1828 				palette[765+i] = c;
1829 			}
1830 
1831 //  we also need to swap the data entries as well.  black is white and white is black
1832 
1833 			for (i = 0; i < ptr-font->ft_data; i++) {
1834 				if (font->ft_data[i] == 0)
1835 					font->ft_data[i] = 255;
1836 				else if (font->ft_data[i] == 255)
1837 					font->ft_data[i] = 0;
1838 			}
1839 
1840 		}
1841 #endif
1842 
1843 		build_colormap_good( (ubyte *)&palette, colormap, freq );
1844 
1845 		colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR;              // changed from colormap[255] = 255 to this for macintosh
1846 
1847 		decode_data_asm(font->ft_data, ptr - font->ft_data, colormap, freq );
1848 
1849 	}
1850 
1851 	cfclose(fontfile);
1852 
1853 #ifdef OGL
1854 	if (font->ft_bitmaps)
1855 		d_free( font->ft_bitmaps );
1856 	gr_free_bitmap_data(&font->ft_parent_bitmap);
1857 //	ogl_freebmtexture(&font->ft_parent_bitmap);
1858 
1859 	ogl_init_font(font);
1860 #endif
1861 }
1862 
1863 
gr_set_fontcolor(int fg,int bg)1864 void gr_set_fontcolor( int fg, int bg )
1865 {
1866 	FG_COLOR    = fg;
1867 	BG_COLOR    = bg;
1868 }
1869 
gr_set_curfont(grs_font * new)1870 void gr_set_curfont( grs_font * new )
1871 {
1872 	FONT = new;
1873 }
1874 
1875 
gr_internal_string_clipped(int x,int y,char * s)1876 int gr_internal_string_clipped(int x, int y, char *s )
1877 {
1878 	unsigned char * fp;
1879 	char * text_ptr, * next_row, * text_ptr1;
1880 	int r, BitMask, i, bits, width, spacing, letter, underline;
1881 	int x1 = x, last_x;
1882 
1883         bits=0;
1884 
1885 	next_row = s;
1886 
1887 	while (next_row != NULL )
1888 	{
1889 		text_ptr1 = next_row;
1890 		next_row = NULL;
1891 
1892 		x = x1;
1893 		if (x==0x8000)			//centered
1894 			x = get_centered_x(text_ptr1);
1895 
1896 		last_x = x;
1897 
1898 		for (r=0; r<FHEIGHT; r++)	{
1899 			text_ptr = text_ptr1;
1900 			x = last_x;
1901 
1902 			while (*text_ptr)	{
1903 				if (*text_ptr == '\n' )	{
1904 					next_row = &text_ptr[1];
1905 					break;
1906 				}
1907 
1908 				if (*text_ptr == CC_COLOR) {
1909 					FG_COLOR = *(text_ptr+1);
1910 					text_ptr += 2;
1911 					continue;
1912 				}
1913 
1914 				if (*text_ptr == CC_LSPACING) {
1915 					Int3();	//	Warning: skip lines not supported for clipped strings.
1916 					text_ptr += 2;
1917 					continue;
1918 				}
1919 
1920 				underline = 0;
1921 				if (*text_ptr == CC_UNDERLINE )	{
1922 					if ((r==FBASELINE+2) || (r==FBASELINE+3))
1923 						underline = 1;
1924 					text_ptr++;
1925 				}
1926 
1927 				get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
1928 
1929 				letter = *text_ptr-FMINCHAR;
1930 
1931 				if (!INFONT(letter)) {	//not in font, draw as space
1932 					x += spacing;
1933 					text_ptr++;
1934 					continue;
1935 				}
1936 
1937 				if (FFLAGS & FT_PROPORTIONAL)
1938 					fp = FCHARS[letter];
1939 				else
1940 					fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
1941 
1942 				if (underline)	{
1943 					for (i=0; i< width; i++ )	{
1944 						gr_setcolor(FG_COLOR);
1945 						gr_pixel( x++, y );
1946 					}
1947 				} else {
1948 					fp += BITS_TO_BYTES(width)*r;
1949 
1950 					BitMask = 0;
1951 
1952 					for (i=0; i< width; i++ )	{
1953 						if (BitMask==0) {
1954 							bits = *fp++;
1955 							BitMask = 0x80;
1956 						}
1957 						if (bits & BitMask)
1958 							gr_setcolor(FG_COLOR);
1959 						else
1960 							gr_setcolor(BG_COLOR);
1961 						gr_pixel( x++, y );
1962 						BitMask >>= 1;
1963 					}
1964 				}
1965 
1966 				x += spacing-width;		//for kerning
1967 
1968 				text_ptr++;
1969 			}
1970 			y++;
1971 		}
1972 	}
1973 	return 0;
1974 }
1975 
gr_internal_string_clipped_m(int x,int y,char * s)1976 int gr_internal_string_clipped_m(int x, int y, char *s )
1977 {
1978 	unsigned char * fp;
1979 	char * text_ptr, * next_row, * text_ptr1;
1980 	int r, BitMask, i, bits, width, spacing, letter, underline;
1981 	int x1 = x, last_x;
1982 
1983         bits=0;
1984 
1985 	next_row = s;
1986 
1987 	while (next_row != NULL )
1988 	{
1989 		text_ptr1 = next_row;
1990 		next_row = NULL;
1991 
1992 		x = x1;
1993 		if (x==0x8000)			//centered
1994 			x = get_centered_x(text_ptr1);
1995 
1996 		last_x = x;
1997 
1998 		for (r=0; r<FHEIGHT; r++)	{
1999 			x = last_x;
2000 
2001 			text_ptr = text_ptr1;
2002 
2003 			while (*text_ptr)	{
2004 				if (*text_ptr == '\n' )	{
2005 					next_row = &text_ptr[1];
2006 					break;
2007 				}
2008 
2009 				if (*text_ptr == CC_COLOR) {
2010 					FG_COLOR = *(text_ptr+1);
2011 					text_ptr += 2;
2012 					continue;
2013 				}
2014 
2015 				if (*text_ptr == CC_LSPACING) {
2016 					Int3();	//	Warning: skip lines not supported for clipped strings.
2017 					text_ptr += 2;
2018 					continue;
2019 				}
2020 
2021 				underline = 0;
2022 				if (*text_ptr == CC_UNDERLINE )	{
2023 					if ((r==FBASELINE+2) || (r==FBASELINE+3))
2024 						underline = 1;
2025 					text_ptr++;
2026 				}
2027 
2028 				get_char_width(text_ptr[0],text_ptr[1],&width,&spacing);
2029 
2030 				letter = *text_ptr-FMINCHAR;
2031 
2032 				if (!INFONT(letter)) {	//not in font, draw as space
2033 					x += spacing;
2034 					text_ptr++;
2035 					continue;
2036 				}
2037 
2038 				if (FFLAGS & FT_PROPORTIONAL)
2039 					fp = FCHARS[letter];
2040 				else
2041 					fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT;
2042 
2043 				if (underline)	{
2044 					for (i=0; i< width; i++ )	{
2045 						gr_setcolor(FG_COLOR);
2046 						gr_pixel( x++, y );
2047 					}
2048 				} else {
2049 					fp += BITS_TO_BYTES(width)*r;
2050 
2051 					BitMask = 0;
2052 
2053 					for (i=0; i< width; i++ )	{
2054 						if (BitMask==0) {
2055 							bits = *fp++;
2056 							BitMask = 0x80;
2057 						}
2058 						if (bits & BitMask)	{
2059 							gr_setcolor(FG_COLOR);
2060 							gr_pixel( x++, y );
2061 						} else {
2062 							x++;
2063 						}
2064 						BitMask >>= 1;
2065 					}
2066 				}
2067 
2068 				x += spacing-width;		//for kerning
2069 
2070 				text_ptr++;
2071 			}
2072 			y++;
2073 		}
2074 	}
2075 	return 0;
2076 }
2077