Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 1
 
2
#include 
3
#include 
4
#include 
5
#include 
6
7
 
8
9
 
10
#include "SDL_ttf.h"
11
12
 
13
#define UNICODE(c)	c
14
15
 
16
static int round(float x)
17
{
18
	int value;
19
20
 
21
	if ( x > value ) {
22
		value = value + 1;
23
	} else
24
	if ( x < value ) {
25
		value = value - 1;
26
	}
27
	return value;
28
}
29
30
 
31
struct glyph {
32
	int cached;
33
	TT_Raster_Map bitmap;
34
	TT_Raster_Map pixmap;
35
	int minx;
36
	int maxx;
37
	int miny;
38
	int maxy;
39
	int advance;
40
};
41
42
 
43
struct _TTF_Font {
44
	TT_Face face;
45
	TT_Instance inst;
46
	TT_Glyph glyph;
47
	TT_CharMap map;
48
49
 
50
	int pointsize;
51
	int height;  /* ascent - descent */
52
	float ascent;
53
	float descent;
54
	float lineskip;
55
56
 
57
	int style;
58
59
 
60
	int glyph_overhang;
61
	float glyph_italics;
62
63
 
64
	struct glyph *current;
65
	struct glyph cache[256];
66
	struct glyph scratch;
67
};
68
69
 
70
static TT_Engine engine;
71
72
 
73
{
74
	int error;
75
76
 
77
	if ( error ) {
78
		SDL_SetError("Couldn't init FreeType engine");
79
		return(-1);
80
	}
81
	return(0);
82
}
83
84
 
85
{
86
	TTF_Font *font;
87
	TT_Face_Properties properties;
88
	TT_Instance_Metrics imetrics;
89
	int i, n;
90
	TT_UShort platform, encoding;
91
	TT_Error error;
92
93
 
94
	if ( font == NULL ) {
95
		SDL_SetError("Out of memory");
96
		return(NULL);
97
	}
98
	memset(font, 0, sizeof(*font));
99
100
 
101
	error = TT_Open_Face(engine, file, &font->face);
102
	if ( error ) {
103
		SDL_SetError("Couldn't load font file");
104
		free(font);
105
		return(NULL);
106
	}
107
	error = TT_New_Glyph(font->face, &font->glyph);
108
	if ( error ) {
109
		SDL_SetError("Couldn't create glyph container");
110
		TTF_CloseFont(font);
111
		return(NULL);
112
	}
113
	error = TT_New_Instance(font->face, &font->inst);
114
	if ( error ) {
115
		SDL_SetError("Couldn't create font instance");
116
		TTF_CloseFont(font);
117
		return(NULL);
118
	}
119
120
 
121
	error = TT_Set_Instance_Resolutions(font->inst, 72, 72);
122
	if ( error ) {
123
		SDL_SetError("Couldn't set font resolution");
124
		TTF_CloseFont(font);
125
		return(NULL);
126
	}
127
	error = TT_Set_Instance_CharSize(font->inst, ptsize*64);
128
	if ( error ) {
129
		SDL_SetError("Couldn't set font size");
130
		TTF_CloseFont(font);
131
		return(NULL);
132
	}
133
134
 
135
	n = TT_Get_CharMap_Count(font->face);
136
	for ( i=0; i
137
		TT_Get_CharMap_ID(font->face, i, &platform, &encoding);
138
		if ( ((platform == TT_PLATFORM_MICROSOFT) &&
139
		                  (encoding == TT_MS_ID_UNICODE_CS)) ||
140
		     ((platform == TT_PLATFORM_APPLE_UNICODE) &&
141
		                  (encoding == TT_APPLE_ID_DEFAULT)) ) {
142
			TT_Get_CharMap(font->face, i, &font->map);
143
			break;
144
		}
145
	}
146
	if ( i == n ) {
147
		SDL_SetError("Font doesn't have a Unicode mapping");
148
		TTF_CloseFont(font);
149
		return(NULL);
150
	}
151
152
 
153
	TT_Get_Face_Properties(font->face, &properties );
154
	TT_Get_Instance_Metrics(font->inst, &imetrics);
155
	font->pointsize = imetrics.y_ppem;
156
	font->ascent = (float)properties.horizontal->Ascender /
157
	                properties.header->Units_Per_EM;
158
	font->ascent *= font->pointsize;
159
	font->descent = (float)properties.horizontal->Descender /
160
	                 properties.header->Units_Per_EM;
161
	font->descent *= font->pointsize;
162
	font->lineskip = (float)properties.horizontal->Line_Gap /
163
	                  properties.header->Units_Per_EM;
164
	font->lineskip *= font->pointsize;
165
	font->height = round(font->ascent - font->descent);
166
167
 
168
	font->style = TTF_STYLE_NORMAL;
169
	font->glyph_overhang = font->pointsize/10;
170
	/* x offset = cos(((90.0-12)/360)*2*M_PI), or 12 degree angle */
171
	font->glyph_italics = 0.207;
172
	font->glyph_italics *= font->height;
173
174
 
175
}
176
177
 
178
{
179
	if ( glyph->bitmap.bitmap ) {
180
		free(glyph->bitmap.bitmap);
181
		glyph->bitmap.bitmap = 0;
182
	}
183
	if ( glyph->pixmap.bitmap ) {
184
		free(glyph->pixmap.bitmap);
185
		glyph->pixmap.bitmap = 0;
186
	}
187
	glyph->cached = 0;
188
}
189
190
 
191
{
192
	int i;
193
194
 
195
		if ( font->cache[i].cached ) {
196
			Flush_Glyph(&font->cache[i]);
197
		}
198
	}
199
	if ( font->scratch.cached ) {
200
		Flush_Glyph(&font->scratch);
201
	}
202
}
203
204
 
205
{
206
	TT_UShort index;
207
	TT_Glyph_Metrics metrics;
208
	TT_Outline outline;
209
	int x_offset;
210
	int y_offset;
211
	TT_Error error;
212
213
 
214
	index = TT_Char_Index(font->map, UNICODE(ch));
215
	error = TT_Load_Glyph(font->inst, font->glyph, index, TTLOAD_DEFAULT);
216
	if ( error ) return error;
217
218
 
219
	TT_Get_Glyph_Metrics(font->glyph, &metrics);
220
	glyph->minx = (metrics.bbox.xMin & -64) / 64;
221
	glyph->maxx = ((metrics.bbox.xMax + 63) & -64) / 64;
222
	glyph->miny = (metrics.bbox.yMin & -64) / 64;
223
	glyph->maxy = ((metrics.bbox.yMax + 63) & -64) / 64;
224
	glyph->advance = (metrics.advance & -64) / 64;
225
226
 
227
	if ( font->style & TTF_STYLE_BOLD ) {
228
		glyph->maxx += font->glyph_overhang;
229
	}
230
	if ( font->style & TTF_STYLE_ITALIC ) {
231
		glyph->maxx += round(font->glyph_italics);
232
	}
233
234
 
235
	glyph->bitmap.width = ((glyph->maxx - glyph->minx) + 7) & ~7;
236
	glyph->bitmap.rows = font->height;
237
	glyph->bitmap.cols = glyph->bitmap.width/8;
238
	glyph->bitmap.flow = TT_Flow_Down;
239
	glyph->bitmap.size = (glyph->bitmap.rows * glyph->bitmap.cols);
240
	if ( glyph->bitmap.size ) {
241
		glyph->bitmap.bitmap = malloc(glyph->bitmap.size);
242
		if ( ! glyph->bitmap.bitmap ) {
243
			error = TT_Err_Out_Of_Memory;
244
			goto was_error;
245
		}
246
		memset(glyph->bitmap.bitmap, 0, glyph->bitmap.size);
247
	} else {
248
		glyph->bitmap.bitmap = 0;
249
	}
250
251
 
252
	glyph->pixmap.width = ((glyph->maxx - glyph->minx) + 3) & ~3;
253
	glyph->pixmap.rows = font->height;
254
	glyph->pixmap.cols = glyph->pixmap.width;
255
	glyph->pixmap.flow = TT_Flow_Down;
256
	glyph->pixmap.size = (glyph->pixmap.rows * glyph->pixmap.cols);
257
	if ( glyph->pixmap.size ) {
258
		glyph->pixmap.bitmap = malloc(glyph->pixmap.size);
259
		if ( ! glyph->pixmap.bitmap ) {
260
			error = TT_Err_Out_Of_Memory;
261
			goto was_error;
262
		}
263
		memset(glyph->pixmap.bitmap, 0, glyph->pixmap.size);
264
	} else {
265
		glyph->pixmap.bitmap = 0;
266
	}
267
268
 
269
	error = TT_Get_Glyph_Outline(font->glyph, &outline);
270
	/* Handle the italic style */
271
	if ( font->style & TTF_STYLE_ITALIC ) {
272
		TT_Matrix shear;
273
274
 
275
		shear.xy = (int)(font->glyph_italics*(1<<16))/font->height;
276
		shear.yx = 0;
277
		shear.yy = 1<<16;
278
		TT_Transform_Outline(&outline, &shear);
279
	}
280
	x_offset = -glyph->minx * 64;
281
	y_offset = -round(font->descent) * 64;
282
	TT_Translate_Outline(&outline, x_offset, y_offset);
283
	error += TT_Get_Outline_Bitmap(engine, &outline, &glyph->bitmap);
284
	error += TT_Get_Outline_Pixmap(engine, &outline, &glyph->pixmap);
285
	/* Handle the bold style */
286
	if ( font->style & TTF_STYLE_BOLD ) {
287
		int row, col;
288
		int offset;
289
		int pixel;
290
		Uint8 *pixmap;
291
292
 
293
		for ( offset=0; offset < font->glyph_overhang; ++offset ) {
294
			TT_Translate_Outline(&outline, 64, 0);
295
			error += TT_Get_Outline_Bitmap(engine,
296
			                               &outline,&glyph->bitmap);
297
		}
298
		x_offset += font->glyph_overhang*64;
299
300
 
301
		for ( row=glyph->pixmap.rows-1; row >= 0; --row ) {
302
			pixmap = (Uint8 *)glyph->pixmap.bitmap +
303
			                  row*glyph->pixmap.cols;
304
			for (offset=1; offset<=font->glyph_overhang; ++offset) {
305
				for (col=glyph->pixmap.cols-1; col > 0; --col) {
306
					pixel=(pixmap[col]+pixmap[col-1]);
307
					if ( pixel > 4 ) {
308
						pixel = 4;
309
					}
310
					pixmap[col] = (Uint8)pixel;
311
				}
312
			}
313
		}
314
	}
315
	TT_Translate_Outline(&outline, -x_offset, -y_offset);
316
was_error:
317
	if ( error ) {
318
		if ( glyph->bitmap.bitmap ) {
319
			free(glyph->bitmap.bitmap);
320
			glyph->bitmap.bitmap = 0;
321
		}
322
		if ( glyph->pixmap.bitmap ) {
323
			free(glyph->pixmap.bitmap);
324
			glyph->pixmap.bitmap = 0;
325
		}
326
		return error;
327
	}
328
329
 
330
	glyph->cached = ch;
331
	return TT_Err_Ok;
332
}
333
334
 
335
{
336
	int retval;
337
338
 
339
	if ( ch < 256 ) {
340
		font->current = &font->cache[ch];
341
	} else {
342
		if ( font->scratch.cached != ch ) {
343
			Flush_Glyph(&font->scratch);
344
		}
345
		font->current = &font->scratch;
346
	}
347
	if ( ! font->current->cached ) {
348
		retval = Load_Glyph(font, ch, font->current);
349
	}
350
	return retval;
351
}
352
353
 
354
{
355
	Flush_Cache(font);
356
	TT_Close_Face(font->face);
357
	free(font);
358
}
359
360
 
361
{
362
	int i;
363
364
 
365
		unicode[i] = ((const unsigned char *)text)[i];
366
	}
367
	unicode[i] = 0;
368
369
 
370
}
371
372
 
373
{
374
	int i, j;
375
	Uint16 ch;
376
377
 
378
		ch = ((const unsigned char *)utf8)[i];
379
		if ( ch >= 0xF0 ) {
380
			ch  =  (Uint16)(utf8[i]&0x07) << 18;
381
			ch |=  (Uint16)(utf8[++i]&0x3F) << 12;
382
			ch |=  (Uint16)(utf8[++i]&0x3F) << 6;
383
			ch |=  (Uint16)(utf8[++i]&0x3F);
384
		} else
385
		if ( ch >= 0xE0 ) {
386
			ch  =  (Uint16)(utf8[i]&0x3F) << 12;
387
			ch |=  (Uint16)(utf8[++i]&0x3F) << 6;
388
			ch |=  (Uint16)(utf8[++i]&0x3F);
389
		} else
390
		if ( ch >= 0xC0 ) {
391
			ch  =  (Uint16)(utf8[i]&0x3F) << 6;
392
			ch |=  (Uint16)(utf8[++i]&0x3F);
393
		}
394
		unicode[j] = ch;
395
	}
396
	unicode[j] = 0;
397
398
 
399
}
400
401
 
402
{
403
	return(font->height);
404
}
405
406
 
407
{
408
       return(round(font->ascent));
409
}
410
411
 
412
{
413
	return(round(font->descent));
414
}
415
416
 
417
{
418
	return(round(font->lineskip));
419
}
420
421
 
422
                     int* minx, int* maxx, int* miny, int* maxy, int* advance)
423
{
424
	TT_Error error;
425
426
 
427
428
 
429
		return -1;
430
	}
431
432
 
433
		*minx = font->current->minx;
434
	}
435
	if ( maxx ) {
436
		*maxx = font->current->maxx;
437
	}
438
	if ( miny ) {
439
		*miny = font->current->miny;
440
	}
441
	if ( maxy ) {
442
		*maxy = font->current->maxy;
443
	}
444
	if ( advance ) {
445
		*advance = font->current->advance;
446
	}
447
	return 0;
448
}
449
450
 
451
{
452
	Uint16 *unicode_text;
453
	int unicode_len;
454
	int status;
455
456
 
457
	unicode_len = strlen(text);
458
	unicode_text = (Uint16 *)malloc((unicode_len+1)*(sizeof *unicode_text));
459
	if ( unicode_text == NULL ) {
460
		SDL_SetError("Out of memory");
461
		return -1;
462
	}
463
	ASCII_to_UNICODE(unicode_text, text, unicode_len);
464
465
 
466
	status = TTF_SizeUNICODE(font, unicode_text, w, h);
467
468
 
469
	free(unicode_text);
470
	return status;
471
}
472
473
 
474
{
475
	Uint16 *unicode_text;
476
	int unicode_len;
477
	int status;
478
479
 
480
	unicode_len = strlen(text);
481
	unicode_text = (Uint16 *)malloc((unicode_len+1)*(sizeof *unicode_text));
482
	if ( unicode_text == NULL ) {
483
		SDL_SetError("Out of memory");
484
		return -1;
485
	}
486
	UTF8_to_UNICODE(unicode_text, text, unicode_len);
487
488
 
489
	status = TTF_SizeUNICODE(font, unicode_text, w, h);
490
491
 
492
	free(unicode_text);
493
	return status;
494
}
495
496
 
497
{
498
	int status;
499
	const Uint16 *ch;
500
	int x, z, minx, maxx;
501
	TT_Error error;
502
503
 
504
	status = 0;
505
	minx = maxx = 0;
506
507
 
508
	x= 0;
509
	for ( ch=text; *ch; ++ch ) {
510
		error = Find_Glyph(font, *ch);
511
		if ( ! error ) {
512
			z = x + font->current->minx;
513
			if ( minx > z ) {
514
				minx = z;
515
			}
516
			if ( font->style & TTF_STYLE_BOLD ) {
517
				x += font->glyph_overhang;
518
			}
519
			if ( font->current->advance > font->current->maxx ) {
520
				z = x + font->current->advance;
521
			} else {
522
				z = x + font->current->maxx;
523
			}
524
			if ( maxx < z ) {
525
				maxx = z;
526
			}
527
			x += font->current->advance;
528
		}
529
	}
530
531
 
532
	if ( w ) {
533
		*w = (maxx - minx);
534
	}
535
	if ( h ) {
536
		*h = font->height;
537
	}
538
	return status;
539
}
540
541
 
542
*/
543
SDL_Surface *TTF_RenderText_Solid(TTF_Font *font,
544
				const char *text, SDL_Color fg)
545
{
546
	SDL_Surface *textbuf;
547
	Uint16 *unicode_text;
548
	int unicode_len;
549
550
 
551
	unicode_len = strlen(text);
552
	unicode_text = (Uint16 *)malloc((unicode_len+1)*(sizeof *unicode_text));
553
	if ( unicode_text == NULL ) {
554
		SDL_SetError("Out of memory");
555
		return(NULL);
556
	}
557
	ASCII_to_UNICODE(unicode_text, text, unicode_len);
558
559
 
560
	textbuf = TTF_RenderUNICODE_Solid(font, unicode_text, fg);
561
562
 
563
	free(unicode_text);
564
	return(textbuf);
565
}
566
567
 
568
*/
569
SDL_Surface *TTF_RenderUTF8_Solid(TTF_Font *font,
570
				const char *text, SDL_Color fg)
571
{
572
	SDL_Surface *textbuf;
573
	Uint16 *unicode_text;
574
	int unicode_len;
575
576
 
577
	unicode_len = strlen(text);
578
	unicode_text = (Uint16 *)malloc((unicode_len+1)*(sizeof *unicode_text));
579
	if ( unicode_text == NULL ) {
580
		SDL_SetError("Out of memory");
581
		return(NULL);
582
	}
583
	UTF8_to_UNICODE(unicode_text, text, unicode_len);
584
585
 
586
	textbuf = TTF_RenderUNICODE_Solid(font, unicode_text, fg);
587
588
 
589
	free(unicode_text);
590
	return(textbuf);
591
}
592
593
 
594
				const Uint16 *text, SDL_Color fg)
595
{
596
	int xstart, width;
597
	int w, h;
598
	SDL_Surface *textbuf;
599
	SDL_Palette *palette;
600
	const Uint16 *ch;
601
	Uint8 *src, *dst;
602
	int row, col;
603
	TT_Error error;
604
605
 
606
	if ( (TTF_SizeUNICODE(font, text, &w, &h) < 0) || !w ) {
607
		TTF_SetError("Text has zero width");
608
		return(NULL);
609
	}
610
611
 
612
	width = w;
613
	w = (w+7)&~7;
614
	textbuf = SDL_AllocSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0);
615
	if ( textbuf == NULL ) {
616
		return(NULL);
617
	}
618
619
 
620
	palette = textbuf->format->palette;
621
	palette->colors[0].r = 255-fg.r;
622
	palette->colors[0].g = 255-fg.g;
623
	palette->colors[0].b = 255-fg.b;
624
	palette->colors[1].r = fg.r;
625
	palette->colors[1].g = fg.g;
626
	palette->colors[1].b = fg.b;
627
	SDL_SetColorKey(textbuf, SDL_SRCCOLORKEY, 0);
628
629
 
630
	xstart = 0;
631
	for ( ch=text; *ch; ++ch ) {
632
		error = Find_Glyph(font, *ch);
633
		if ( ! error ) {
634
			w = font->current->bitmap.width;
635
			src = (Uint8 *)font->current->bitmap.bitmap;
636
			for ( row = 0; row < h; ++row ) {
637
				dst = (Uint8 *)textbuf->pixels +
638
				               row * textbuf->pitch +
639
				               xstart + font->current->minx;
640
				for ( col = 0; col < w; col += 8 ) {
641
					Uint8 c = *src++;
642
					*dst++ |= (c&0x80)>>7;
643
					c <<= 1;
644
					*dst++ |= (c&0x80)>>7;
645
					c <<= 1;
646
					*dst++ |= (c&0x80)>>7;
647
					c <<= 1;
648
					*dst++ |= (c&0x80)>>7;
649
					c <<= 1;
650
					*dst++ |= (c&0x80)>>7;
651
					c <<= 1;
652
					*dst++ |= (c&0x80)>>7;
653
					c <<= 1;
654
					*dst++ |= (c&0x80)>>7;
655
					c <<= 1;
656
					*dst++ |= (c&0x80)>>7;
657
				}
658
			}
659
			xstart += font->current->advance;
660
			if ( font->style & TTF_STYLE_BOLD ) {
661
				xstart += font->glyph_overhang;
662
			}
663
		}
664
	}
665
	/* Handle the underline style */
666
	if ( font->style & TTF_STYLE_UNDERLINE ) {
667
		int row_offset;
668
669
 
670
		if ( row_offset > font->height ) {
671
			row_offset = font->height-1;
672
		}
673
		memset((Uint8 *)textbuf->pixels+row_offset*textbuf->pitch,
674
								1, width);
675
	}
676
	return(textbuf);
677
}
678
679
 
680
{
681
	SDL_Surface *textbuf;
682
	SDL_Palette *palette;
683
	Uint8 *src, *dst;
684
	int row, col;
685
	TT_Error error;
686
	struct glyph *glyph;
687
688
 
689
	error = Find_Glyph(font, ch);
690
	if ( error ) {
691
		return(NULL);
692
	}
693
	glyph = font->current;
694
695
 
696
	textbuf = SDL_CreateRGBSurface(SDL_SWSURFACE,
697
	              glyph->bitmap.width, glyph->bitmap.rows, 8, 0, 0, 0, 0);
698
	if ( ! textbuf ) {
699
		return(NULL);
700
	}
701
702
 
703
	palette = textbuf->format->palette;
704
	palette->colors[0].r = 255-fg.r;
705
	palette->colors[0].g = 255-fg.g;
706
	palette->colors[0].b = 255-fg.b;
707
	palette->colors[1].r = fg.r;
708
	palette->colors[1].g = fg.g;
709
	palette->colors[1].b = fg.b;
710
	SDL_SetColorKey(textbuf, SDL_SRCCOLORKEY, 0);
711
712
 
713
	src = (Uint8 *)font->current->bitmap.bitmap;
714
	for ( row = 0; row < textbuf->h; ++row ) {
715
		dst = (Uint8 *)textbuf->pixels + row * textbuf->pitch;
716
		for ( col = 0; col < textbuf->w; col += 8 ) {
717
			Uint8 c = *src++;
718
			*dst++ |= (c&0x80)>>7;
719
			c <<= 1;
720
			*dst++ |= (c&0x80)>>7;
721
			c <<= 1;
722
			*dst++ |= (c&0x80)>>7;
723
			c <<= 1;
724
			*dst++ |= (c&0x80)>>7;
725
			c <<= 1;
726
			*dst++ |= (c&0x80)>>7;
727
			c <<= 1;
728
			*dst++ |= (c&0x80)>>7;
729
			c <<= 1;
730
			*dst++ |= (c&0x80)>>7;
731
			c <<= 1;
732
			*dst++ |= (c&0x80)>>7;
733
		}
734
	}
735
736
 
737
	if ( font->style & TTF_STYLE_UNDERLINE ) {
738
		int row_offset;
739
740
 
741
		if ( row_offset > font->height ) {
742
			row_offset = font->height-1;
743
		}
744
		memset((Uint8 *)textbuf->pixels+row_offset*textbuf->pitch,
745
							1, textbuf->w);
746
	}
747
	return(textbuf);
748
}
749
750
 
751
 
752
*/
753
SDL_Surface *TTF_RenderText_Shaded(TTF_Font *font,
754
				const char *text, SDL_Color fg, SDL_Color bg)
755
{
756
	SDL_Surface *textbuf;
757
	Uint16 *unicode_text;
758
	int unicode_len;
759
760
 
761
	unicode_len = strlen(text);
762
	unicode_text = (Uint16 *)malloc((unicode_len+1)*(sizeof *unicode_text));
763
	if ( unicode_text == NULL ) {
764
		SDL_SetError("Out of memory");
765
		return(NULL);
766
	}
767
	ASCII_to_UNICODE(unicode_text, text, unicode_len);
768
769
 
770
	textbuf = TTF_RenderUNICODE_Shaded(font, unicode_text, fg, bg);
771
772
 
773
	free(unicode_text);
774
	return(textbuf);
775
}
776
777
 
778
*/
779
SDL_Surface *TTF_RenderUTF8_Shaded(TTF_Font *font,
780
				const char *text, SDL_Color fg, SDL_Color bg)
781
{
782
	SDL_Surface *textbuf;
783
	Uint16 *unicode_text;
784
	int unicode_len;
785
786
 
787
	unicode_len = strlen(text);
788
	unicode_text = (Uint16 *)malloc((unicode_len+1)*(sizeof *unicode_text));
789
	if ( unicode_text == NULL ) {
790
		SDL_SetError("Out of memory");
791
		return(NULL);
792
	}
793
	UTF8_to_UNICODE(unicode_text, text, unicode_len);
794
795
 
796
	textbuf = TTF_RenderUNICODE_Shaded(font, unicode_text, fg, bg);
797
798
 
799
	free(unicode_text);
800
	return(textbuf);
801
}
802
803
 
804
				const Uint16 *text, SDL_Color fg, SDL_Color bg)
805
{
806
	int xstart, width;
807
	int w, h;
808
	SDL_Surface *textbuf;
809
	SDL_Palette *palette;
810
	int index;
811
	int rdiff, gdiff, bdiff;
812
	const Uint16 *ch;
813
	Uint8 *src, *dst;
814
	int row, col;
815
	TT_Error error;
816
817
 
818
	if ( (TTF_SizeUNICODE(font, text, &w, &h) < 0) || !w ) {
819
		TTF_SetError("Text has zero width");
820
		return(NULL);
821
	}
822
823
 
824
	width = w;
825
	w = (w+3)&~3;
826
	textbuf = SDL_AllocSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0);
827
	if ( textbuf == NULL ) {
828
		return(NULL);
829
	}
830
831
 
832
	palette = textbuf->format->palette;
833
	rdiff = fg.r - bg.r;
834
	gdiff = fg.g - bg.g;
835
	bdiff = fg.b - bg.b;
836
	for ( index=0; index<5; ++index ) {
837
		palette->colors[index].r = bg.r + (index*rdiff)/4;
838
		palette->colors[index].g = bg.g + (index*gdiff)/4;
839
		palette->colors[index].b = bg.b + (index*bdiff)/4;
840
	}
841
	/* The other 3 levels are used as overflow when ORing pixels */
842
	for ( ; index<8; ++index ) {
843
		palette->colors[index] = palette->colors[4];
844
	}
845
846
 
847
	xstart = 0;
848
	for ( ch=text; *ch; ++ch ) {
849
		error = Find_Glyph(font, *ch);
850
		if ( ! error ) {
851
			w = font->current->pixmap.width;
852
			src = (Uint8 *)font->current->pixmap.bitmap;
853
			for ( row = 0; row < h; ++row ) {
854
				dst = (Uint8 *)textbuf->pixels +
855
				               row * textbuf->pitch +
856
				               xstart + font->current->minx;
857
				for ( col=w; col>0; col -= 4 ) {
858
					*dst++ |= *src++;
859
					*dst++ |= *src++;
860
					*dst++ |= *src++;
861
					*dst++ |= *src++;
862
				}
863
			}
864
			xstart += font->current->advance;
865
			if ( font->style & TTF_STYLE_BOLD ) {
866
				xstart += font->glyph_overhang;
867
			}
868
		}
869
	}
870
	/* Handle the underline style */
871
	if ( font->style & TTF_STYLE_UNDERLINE ) {
872
		int row_offset;
873
874
 
875
		if ( row_offset > font->height ) {
876
			row_offset = font->height-1;
877
		}
878
		memset((Uint8 *)textbuf->pixels+row_offset*textbuf->pitch,
879
								4, width);
880
	}
881
	return(textbuf);
882
}
883
884
 
885
				Uint16 ch, SDL_Color fg, SDL_Color bg)
886
{
887
	SDL_Surface *textbuf;
888
	SDL_Palette *palette;
889
	int index;
890
	int rdiff, gdiff, bdiff;
891
	Uint8 *src, *dst;
892
	int row, col;
893
	TT_Error error;
894
	struct glyph *glyph;
895
896
 
897
	error = Find_Glyph(font, ch);
898
	if ( error ) {
899
		return(NULL);
900
	}
901
	glyph = font->current;
902
903
 
904
	textbuf = SDL_CreateRGBSurface(SDL_SWSURFACE,
905
	              glyph->pixmap.width, glyph->pixmap.rows, 8, 0, 0, 0, 0);
906
	if ( ! textbuf ) {
907
		return(NULL);
908
	}
909
910
 
911
	palette = textbuf->format->palette;
912
	rdiff = fg.r - bg.r;
913
	gdiff = fg.g - bg.g;
914
	bdiff = fg.b - bg.b;
915
	for ( index=0; index<5; ++index ) {
916
		palette->colors[index].r = bg.r + (index*rdiff)/4;
917
		palette->colors[index].g = bg.g + (index*gdiff)/4;
918
		palette->colors[index].b = bg.b + (index*bdiff)/4;
919
	}
920
921
 
922
	for ( row=0; rowh; ++row ) {
923
		src = glyph->pixmap.bitmap + row * glyph->pixmap.cols;
924
		dst = (Uint8 *)textbuf->pixels + row * textbuf->pitch;
925
		memcpy(dst, src, glyph->pixmap.cols);
926
	}
927
928
 
929
	if ( font->style & TTF_STYLE_UNDERLINE ) {
930
		int row_offset;
931
932
 
933
		if ( row_offset > font->height ) {
934
			row_offset = font->height-1;
935
		}
936
		memset((Uint8 *)textbuf->pixels+row_offset*textbuf->pitch,
937
							4, glyph->pixmap.cols);
938
	}
939
	return(textbuf);
940
}
941
942
 
943
*/
944
SDL_Surface *TTF_RenderText_Blended(TTF_Font *font,
945
				const char *text, SDL_Color fg)
946
{
947
	SDL_Surface *textbuf;
948
	Uint16 *unicode_text;
949
	int unicode_len;
950
951
 
952
	unicode_len = strlen(text);
953
	unicode_text = (Uint16 *)malloc((unicode_len+1)*(sizeof *unicode_text));
954
	if ( unicode_text == NULL ) {
955
		SDL_SetError("Out of memory");
956
		return(NULL);
957
	}
958
	ASCII_to_UNICODE(unicode_text, text, unicode_len);
959
960
 
961
	textbuf = TTF_RenderUNICODE_Blended(font, unicode_text, fg);
962
963
 
964
	free(unicode_text);
965
	return(textbuf);
966
}
967
968
 
969
*/
970
SDL_Surface *TTF_RenderUTF8_Blended(TTF_Font *font,
971
				const char *text, SDL_Color fg)
972
{
973
	SDL_Surface *textbuf;
974
	Uint16 *unicode_text;
975
	int unicode_len;
976
977
 
978
	unicode_len = strlen(text);
979
	unicode_text = (Uint16 *)malloc((unicode_len+1)*(sizeof *unicode_text));
980
	if ( unicode_text == NULL ) {
981
		SDL_SetError("Out of memory");
982
		return(NULL);
983
	}
984
	UTF8_to_UNICODE(unicode_text, text, unicode_len);
985
986
 
987
	textbuf = TTF_RenderUNICODE_Blended(font, unicode_text, fg);
988
989
 
990
	free(unicode_text);
991
	return(textbuf);
992
}
993
994
 
995
				const Uint16 *text, SDL_Color fg)
996
{
997
	int xstart, width;
998
	int w, h;
999
	SDL_Surface *textbuf;
1000
#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) >= \
1001
    SDL_VERSIONNUM(1, 1, 5)			/* The great alpha flip */
1002
	Uint32 alpha_table[] = {
1003
		(0)<<24,      (255-128)<<24, (255-64)<<24, (255-32)<<24,
1004
		(255)<<24,    (255)<<24,     (255)<<24,    (255)<<24
1005
	};
1006
#else
1007
	Uint32 alpha_table[] = {
1008
		(255<<24), (128<<24), (64<<24), (32<<24), 0, 0, 0, 0
1009
	};
1010
#endif
1011
	Uint32 pixel;
1012
	const Uint16 *ch;
1013
	Uint8 *src;
1014
	Uint32 *dst;
1015
	int row, col;
1016
	TT_Error error;
1017
1018
 
1019
	if ( (TTF_SizeUNICODE(font, text, &w, &h) < 0) || !w ) {
1020
		TTF_SetError("Text has zero width");
1021
		return(NULL);
1022
	}
1023
1024
 
1025
	width = w;
1026
	w = (w+3)&~3;
1027
	textbuf = SDL_AllocSurface(SDL_SWSURFACE, w, h, 32,
1028
	                           0x00FF0000, 0x0000FF00, 0x000000FF,
1029
	                           0xFF000000);
1030
	if ( textbuf == NULL ) {
1031
		return(NULL);
1032
	}
1033
1034
 
1035
	xstart = 0;
1036
	for ( ch=text; *ch; ++ch ) {
1037
		error = Find_Glyph(font, *ch);
1038
		if ( ! error ) {
1039
			w = font->current->pixmap.width;
1040
			src = (Uint8 *)font->current->pixmap.bitmap;
1041
			for ( row = 0; row < h; ++row ) {
1042
				dst = (Uint32 *)textbuf->pixels +
1043
				               row * textbuf->pitch/4 +
1044
				               xstart + font->current->minx;
1045
				for ( col=w; col>0; col -= 4 ) {
1046
					*dst++ |= *src++;
1047
					*dst++ |= *src++;
1048
					*dst++ |= *src++;
1049
					*dst++ |= *src++;
1050
				}
1051
			}
1052
			xstart += font->current->advance;
1053
			if ( font->style & TTF_STYLE_BOLD ) {
1054
				xstart += font->glyph_overhang;
1055
			}
1056
		}
1057
	}
1058
1059
 
1060
	if ( font->style & TTF_STYLE_UNDERLINE ) {
1061
		int row_offset;
1062
1063
 
1064
		if ( row_offset > font->height ) {
1065
			row_offset = font->height-1;
1066
		}
1067
		dst = (Uint32 *)textbuf->pixels+row_offset*textbuf->pitch/4;
1068
		for ( col=width; col > 0; ++col ) {
1069
			*dst++ = 4;
1070
		}
1071
	}
1072
1073
 
1074
	pixel = (fg.r<<16)|(fg.g<<8)|fg.b;
1075
	for ( xstart = 0; xstart < 8; ++xstart ) {
1076
		alpha_table[xstart] |= pixel;
1077
	}
1078
1079
 
1080
	for ( row = 0; row < textbuf->h; ++row ) {
1081
		dst = (Uint32 *)textbuf->pixels + row * textbuf->pitch/4;
1082
		for ( col=textbuf->w; col>0; col -= 4 ) {
1083
			*dst = alpha_table[*dst];
1084
			++dst;
1085
			*dst = alpha_table[*dst];
1086
			++dst;
1087
			*dst = alpha_table[*dst];
1088
			++dst;
1089
			*dst = alpha_table[*dst];
1090
			++dst;
1091
		}
1092
	}
1093
	return(textbuf);
1094
}
1095
1096
 
1097
{
1098
	SDL_Surface *textbuf;
1099
#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) >= \
1100
    SDL_VERSIONNUM(1, 1, 5)			/* The great alpha flip */
1101
	Uint32 alpha_table[] = {
1102
		(0)<<24,      (255-128)<<24, (255-64)<<24, (255-32)<<24,
1103
		(255)<<24,    (255)<<24,     (255)<<24,    (255)<<24
1104
	};
1105
#else
1106
	Uint32 alpha_table[] = {
1107
		(255<<24), (128<<24), (64<<24), (32<<24), 0, 0, 0, 0
1108
	};
1109
#endif
1110
	Uint32 pixel;
1111
	Uint8 *src;
1112
	Uint32 *dst;
1113
	int row, col;
1114
	TT_Error error;
1115
	struct glyph *glyph;
1116
1117
 
1118
	error = Find_Glyph(font, ch);
1119
	if ( error ) {
1120
		return(NULL);
1121
	}
1122
	glyph = font->current;
1123
1124
 
1125
	textbuf = SDL_CreateRGBSurface(SDL_SWSURFACE,
1126
	              glyph->pixmap.width, glyph->pixmap.rows, 32,
1127
	              0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
1128
	if ( ! textbuf ) {
1129
		return(NULL);
1130
	}
1131
1132
 
1133
	for ( row=0; rowh; ++row ) {
1134
		src = glyph->pixmap.bitmap + row * glyph->pixmap.cols;
1135
		dst = (Uint32 *)textbuf->pixels + row * textbuf->pitch/4;
1136
		for ( col=0; colpixmap.cols; ++col ) {
1137
			*dst++ = *src++;
1138
		}
1139
	}
1140
1141
 
1142
	if ( font->style & TTF_STYLE_UNDERLINE ) {
1143
		int row_offset;
1144
1145
 
1146
		if ( row_offset > font->height ) {
1147
			row_offset = font->height-1;
1148
		}
1149
		dst = (Uint32 *)textbuf->pixels+row_offset*textbuf->pitch/4;
1150
		for ( col=glyph->pixmap.cols; col > 0; ++col ) {
1151
			*dst++ = 4;
1152
		}
1153
	}
1154
1155
 
1156
	pixel = (fg.r<<16)|(fg.g<<8)|fg.b;
1157
	for ( col = 0; col < 8; ++col ) {
1158
		alpha_table[col] |= pixel;
1159
	}
1160
1161
 
1162
	for ( row = 0; row < textbuf->h; ++row ) {
1163
		dst = (Uint32 *)textbuf->pixels + row * textbuf->pitch/4;
1164
		for ( col=textbuf->w; col>0; col -= 4 ) {
1165
			*dst = alpha_table[*dst];
1166
			++dst;
1167
			*dst = alpha_table[*dst];
1168
			++dst;
1169
			*dst = alpha_table[*dst];
1170
			++dst;
1171
			*dst = alpha_table[*dst];
1172
			++dst;
1173
		}
1174
	}
1175
	return(textbuf);
1176
}
1177
1178
 
1179
{
1180
	font->style = style;
1181
	Flush_Cache(font);
1182
}
1183
1184
 
1185
{
1186
	return(font->style);
1187
}
1188
1189
 
1190
{
1191
	TT_Done_FreeType(engine);
1192
}
1193
>