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