1 /* vim:expandtab:ts=2 sw=2:
2 */
3 /* Grafx2 - The Ultimate 256-color bitmap paint program
4
5 Copyright owned by various GrafX2 authors, see COPYRIGHT.txt for details.
6
7 Grafx2 is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; version 2
10 of the License.
11
12 Grafx2 is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Grafx2; if not, see <http://www.gnu.org/licenses/>
19 */
20
21 // Pour désactiver le support TrueType, définir NOTTF
22 // To disable TrueType support, define NOTTF
23
24 #include <string.h>
25 #include <stdlib.h>
26 #include <ctype.h> // tolower()
27
28 // TrueType
29 #ifndef NOTTF
30 #include <SDL_ttf.h>
31
32 #if defined(__CAANOO__) || defined(__WIZ__) || defined(__GP2X__)
33 // No fontconfig
34 #elif defined(USE_FC) && !defined(NOTTF)
35 #include <fontconfig/fontconfig.h>
36 #endif
37 #endif
38
39 #if defined(__macosx__)
40 #import <CoreFoundation/CoreFoundation.h>
41 #import <sys/param.h>
42 #endif
43
44 #ifdef _MSC_VER
45 #include <stdio.h>
46 #define strdup _strdup
47 #if _MSC_VER < 1900
48 #define snprintf _snprintf
49 #endif
50 #endif
51 #if defined(WIN32)
52 #include <windows.h>
53 #include <malloc.h>
54 #endif
55
56 #if defined(USE_SDL) || defined(USE_SDL2)
57 #include <SDL_image.h>
58 #include "sdlscreen.h"
59 #endif
60
61 #include "struct.h"
62 #include "global.h"
63 #include "io.h"
64 #include "errors.h"
65 #include "windows.h"
66 #include "misc.h"
67 #include "setup.h"
68 #include "loadsave.h"
69 #include "SFont.h"
70
71 /**
72 * Element of the font linked list
73 */
74 typedef struct T_Font
75 {
76 char * Name;
77 int Is_truetype;
78 int Is_bitmap;
79 char Label[22];
80
81 // Liste chainée simple
82 struct T_Font * Next;
83 struct T_Font * Previous;
84 } T_Font;
85
86 /**
87 * Head of the font linked list
88 */
89 T_Font * font_list_start;
90
91 // Inspiré par Allegro
92 #define EXTID(a,b,c) ((((a)&255)<<16) | (((b)&255)<<8) | (((c)&255)))
93 #define EXTID4(a,b,c,d) ((((a)&255)<<24) | (((b)&255)<<16) | (((c)&255)<<8) | (((d)&255)))
94
Compare_fonts(T_Font * font_1,T_Font * font_2)95 static int Compare_fonts(T_Font * font_1, T_Font * font_2)
96 {
97 if (font_1->Is_bitmap && !font_2->Is_bitmap)
98 return -1;
99 if (font_2->Is_bitmap && !font_1->Is_bitmap)
100 return 1;
101 return strcmp(font_1->Label, font_2->Label);
102 }
103
Insert_font(T_Font * font)104 static void Insert_font(T_Font * font)
105 {
106 // Gestion Liste
107 font->Next = NULL;
108 font->Previous = NULL;
109 if (font_list_start==NULL)
110 {
111 // Premiere (liste vide)
112 font_list_start = font;
113 }
114 else
115 {
116 int compare;
117 compare = Compare_fonts(font, font_list_start);
118 if (compare<=0)
119 {
120 if (compare==0 && !strcmp(font->Name, font_list_start->Name))
121 {
122 // Doublon
123 free(font->Name);
124 free(font);
125 return;
126 }
127 // Avant la premiere
128 font->Next=font_list_start;
129 font_list_start=font;
130 }
131 else
132 {
133 T_Font *searched_font;
134 searched_font=font_list_start;
135 while (searched_font->Next && (compare=Compare_fonts(font, searched_font->Next))>0)
136 searched_font=searched_font->Next;
137 // Après searched_font
138 if (compare==0 && strcmp(font->Name, searched_font->Next->Name)==0)
139 {
140 // Doublon
141 free(font->Name);
142 free(font);
143 return;
144 }
145 font->Next=searched_font->Next;
146 searched_font->Next=font;
147 }
148 }
149 }
150
151 // Ajout d'une fonte à la liste.
Add_font(const char * name,const char * font_name)152 static void Add_font(const char *name, const char * font_name)
153 {
154 T_Font * font;
155 int size=strlen(name)+1;
156 int index;
157
158 // Détermination du type:
159
160 #if defined(__macosx__)
161 char strFontName[512];
162 CFStringRef CFSFontName;// = CFSTR(name);
163
164 if (size < 6) return;
165
166 CFSFontName = CFStringCreateWithBytes(NULL, (UInt8 *) name, size - 1, kCFStringEncodingASCII, false);
167 // Fix some funny names
168 CFStringGetCString(CFSFontName, strFontName, 512, kCFStringEncodingASCII);
169
170 // Now we have a printable font name, use it
171 name = strFontName;
172
173 #else
174 if (size<5 ||
175 name[size-5]!='.')
176 return;
177 #endif
178
179 #if defined(WIN32) && defined(NOTTF)
180 // Register font in windows so they will be visible with EnumFontFamiliesEx()
181 if (AddFontResourceExA(name, FR_PRIVATE, 0) > 0)
182 return;
183 #endif
184
185 font = (T_Font *)malloc(sizeof(T_Font));
186
187 switch (EXTID(tolower(name[size-4]), tolower(name[size-3]), tolower(name[size-2])))
188 {
189 case EXTID('t','t','f'):
190 case EXTID('f','o','n'):
191 case EXTID('o','t','f'):
192 case EXTID('p','f','b'):
193 font->Is_truetype = 1;
194 font->Is_bitmap = 0;
195 break;
196 case EXTID('b','m','p'):
197 case EXTID('g','i','f'):
198 case EXTID('j','p','g'):
199 case EXTID('l','b','m'):
200 case EXTID('p','c','x'):
201 case EXTID('p','n','g'):
202 case EXTID('t','g','a'):
203 case EXTID('t','i','f'):
204 case EXTID('x','c','f'):
205 case EXTID('x','p','m'):
206 case EXTID('.','x','v'):
207 font->Is_truetype = 0;
208 font->Is_bitmap = 1;
209 break;
210 default:
211 #if defined(__macosx__)
212 if(strcasecmp(&name[size-6], "dfont") == 0)
213 {
214 font->Is_truetype = 1;
215 font->Is_bitmap = 0;
216 }
217 else
218 {
219 free(font);
220 return;
221 }
222 #else
223 free(font);
224 return;
225 #endif
226 }
227
228 font->Name = strdup(name);
229 // Label
230 memset(font->Label, ' ', sizeof(font->Label));
231 font->Label[19] = '\0';
232 if (font->Is_truetype)
233 font->Label[17]=font->Label[18]='T'; // Logo TT
234 for (index=0; index < 17 && font_name[index]!='\0' && font_name[index]!='.'; index++)
235 font->Label[index]=font_name[index];
236
237 Insert_font(font);
238 }
239
240
241 // Trouve le nom d'une fonte par son numéro
Font_name(int index)242 const char * Font_name(int index)
243 {
244 T_Font *font = font_list_start;
245 if (index < 0 || font == NULL)
246 return "";
247 while (index--)
248 {
249 font = font->Next;
250 if (font == NULL)
251 return "";
252 }
253 return font->Name;
254 }
255
256
257 // Trouve le libellé d'affichage d'une fonte par son numéro
258 // Renvoie un pointeur sur un buffer statique de 20 caracteres.
Font_label(int index)259 const char * Font_label(int index)
260 {
261 T_Font *font = font_list_start;
262
263 font = font_list_start;
264 if (index < 0 || font == NULL)
265 return " ";
266 while (index--)
267 {
268 font = font->Next;
269 if (font == NULL)
270 return " ";
271 }
272 return font->Label;
273 }
274
275
276 // Vérifie si une fonte donnée est TrueType
TrueType_font(int index)277 int TrueType_font(int index)
278 {
279 T_Font *font = font_list_start;
280 if (index < 0 || font == NULL)
281 return 0;
282 while (index--)
283 {
284 font = font->Next;
285 if (font == NULL)
286 return 0;
287 }
288 return font->Is_truetype;
289 }
290
Font_count(void)291 int Font_count(void)
292 {
293 T_Font *font = font_list_start;
294 int count = 0;
295
296 while (font != NULL)
297 {
298 count++;
299 font = font->Next;
300 }
301 return count;
302 }
303
304 #if defined(WIN32) && defined(NOTTF)
EnumFontFamCallback(CONST LOGFONTA * lpelf,CONST TEXTMETRICA * lpntm,DWORD FontType,LPARAM lParam)305 static int CALLBACK EnumFontFamCallback(CONST LOGFONTA *lpelf, CONST TEXTMETRICA *lpntm, DWORD FontType, LPARAM lParam)
306 {
307 char type[3] = { ' ', ' ', '\0' };
308 T_Font * font;
309
310 (void)lParam; // we don't use the custom callback param
311 if (FontType & TRUETYPE_FONTTYPE)
312 type[0] = type[1] = 'T';
313 else if (FontType & RASTER_FONTTYPE)
314 type[0] = 'R'; // Raster font.
315 if (((CONST NEWTEXTMETRICA *)lpntm)->ntmFlags & NTM_TT_OPENTYPE)
316 type[0] = 'O'; // OpenType font
317 font = (T_Font *)malloc(sizeof(T_Font));
318 font->Is_bitmap = 0;
319 font->Is_truetype = 1;
320 snprintf(font->Label, sizeof(font->Label), "%-17.17s%s", lpelf->lfFaceName, type);
321 font->Name = strdup(lpelf->lfFaceName);
322
323 Insert_font(font);
324 return 1; // non-zero : continue enumeration
325 }
326 #endif
327
328
329 // Initialisation à faire une fois au début du programme
Init_text(void)330 void Init_text(void)
331 {
332 char * directory_name;
333 #ifndef NOTTF
334 // Initialisation de TTF
335 TTF_Init();
336 #endif
337
338 // Initialisation des fontes
339 font_list_start = NULL;
340 // Parcours du répertoire "fonts"
341 directory_name = Filepath_append_to_dir(Data_directory, FONTS_SUBDIRECTORY);
342 For_each_file(directory_name, Add_font);
343 free(directory_name);
344 // fonts subdirectory in Config_directory
345 directory_name = Filepath_append_to_dir(Config_directory, "fonts");
346 For_each_file(directory_name, Add_font);
347 free(directory_name);
348
349 #if defined(WIN32)
350 // Parcours du répertoire systeme windows "fonts"
351 #ifndef NOTTF
352 {
353 char * WindowsPath = getenv("windir");
354 if (WindowsPath)
355 {
356 directory_name = Filepath_append_to_dir(WindowsPath, "FONTS");
357 For_each_file(directory_name, Add_font);
358 free(directory_name);
359 }
360 }
361 #else
362 {
363 LOGFONTA lf;
364 HDC dc = GetDC(NULL);
365 memset(&lf, 0, sizeof(lf));
366 lf.lfCharSet = ANSI_CHARSET /* DEFAULT_CHARSET*/;
367 lf.lfPitchAndFamily = 0;
368 //EnumFontsA(dc, NULL, EnumFontCallback, NULL);
369 //EnumFontFamiliesA(dc, NULL, EnumFontFamCallback, 0);
370 EnumFontFamiliesExA(dc, &lf, EnumFontFamCallback, 0, 0);
371 ReleaseDC(NULL, dc);
372 }
373 #endif
374 #elif defined(__macosx__)
375 // Récupération de la liste des fonts avec fontconfig
376 #ifndef NOTTF
377 {
378
379 int i,number;
380 char * home_dir = NULL;
381 const char *font_path_list[3] = {
382 "/System/Library/Fonts",
383 "/Library/Fonts"
384 };
385 number = 2;
386 // Make sure we also search into the user's fonts directory
387 //CFURLRef url = (CFURLRef) CFCopyHomeDirectoryURLForUser(NULL);
388 //CFURLGetFileSystemRepresentation(url, true, (UInt8 *) home_dir, MAXPATHLEN);
389 if (getenv("HOME") != NULL)
390 {
391 home_dir = Filepath_append_to_dir(getenv("HOME"), "Library/Fonts");
392 font_path_list[number++] = home_dir;
393 }
394
395 for(i=0;i<number;i++)
396 For_each_file(font_path_list[i],Add_font);
397
398 free(home_dir);
399 //CFRelease(url);
400 }
401 #endif
402
403 #elif defined(__CAANOO__) || defined(__WIZ__) || defined(__GP2X__)
404 // No fontconfig : Only use fonts from Grafx2
405 #elif defined(USE_FC)
406 #ifndef NOTTF
407 {
408 FcStrList* dirs;
409 FcChar8 * fdir;
410 dirs = FcConfigGetFontDirs(NULL);
411 fdir = FcStrListNext(dirs);
412 while(fdir != NULL)
413 {
414 For_each_file((char *)fdir,Add_font);
415 fdir = FcStrListNext(dirs);
416 }
417
418 FcStrListDone(dirs);
419 }
420 #endif
421 #elif defined(__amigaos4__) || defined(__amigaos__)
422 #ifndef NOTTF
423 For_each_file( "FONTS:_TrueType", Add_font );
424 #endif
425 #elif defined(__AROS__)
426 #ifndef NOTTF
427 For_each_file( "FONTS:TrueType", Add_font );
428 #endif
429 #elif defined(__BEOS__)
430 #ifndef NOTTF
431 For_each_file("/etc/fonts/ttfonts", Add_font);
432 #endif
433 #elif defined(__HAIKU__)
434 #ifndef NOTTF
435 For_each_file("/boot/system/data/fonts/ttfonts/", Add_font);
436 #endif
437 #elif defined(__SKYOS__)
438 #ifndef NOTTF
439 For_each_file("/boot/system/fonts", Add_font);
440 #endif
441 #elif defined(__MINT__)
442 #ifndef NOTTF
443 For_each_file("C:/BTFONTS", Add_font);
444 #endif
445
446 #endif
447 }
448
449 // Informe si texte.c a été compilé avec l'option de support TrueType ou pas.
TrueType_is_supported()450 int TrueType_is_supported()
451 {
452 #if !defined(NOTTF) || defined(WIN32)
453 return 1;
454 #else
455 return 0;
456 #endif
457 }
458
Uninit_text(void)459 void Uninit_text(void)
460 {
461 #ifndef NOTTF
462 TTF_Quit();
463 #if defined(USE_FC)
464 FcFini();
465 #endif
466 #endif
467 while (font_list_start != NULL)
468 {
469 T_Font * font = font_list_start->Next;
470 free(font_list_start->Name);
471 free(font_list_start);
472 font_list_start = font;
473 }
474 }
475
476 #ifndef NOTTF
Render_text_TTF(const char * str,int font_number,int size,int antialias,int bold,int italic,int * width,int * height,T_Palette palette)477 byte *Render_text_TTF(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height, T_Palette palette)
478 {
479 TTF_Font *font;
480 SDL_Surface * text_surface;
481 byte * new_brush;
482 int style;
483
484 SDL_Color fg_color;
485 SDL_Color bg_color;
486
487 // Chargement de la fonte
488 font=TTF_OpenFont(Font_name(font_number), size);
489 if (!font)
490 {
491 return NULL;
492 }
493
494 // Style
495 style=0;
496 if (italic)
497 style|=TTF_STYLE_ITALIC;
498 if (bold)
499 style|=TTF_STYLE_BOLD;
500 TTF_SetFontStyle(font, style);
501
502 // Colors: Text will be generated as white on black.
503 fg_color.r=fg_color.g=fg_color.b=255;
504 bg_color.r=bg_color.g=bg_color.b=0;
505 // The following is alpha, supposedly unused
506 #if defined(USE_SDL)
507 bg_color.unused=fg_color.unused=255;
508 #elif defined(USE_SDL2)
509 bg_color.a=fg_color.a=255;
510 #endif
511
512 // Text rendering: creates a 8bit surface with its dedicated palette
513 #ifdef __ANDROID__
514 if (antialias)
515 text_surface=TTF_RenderUTF8_Shaded(font, str, fg_color, bg_color );
516 else
517 text_surface=TTF_RenderUTF8_Solid(font, str, fg_color);
518 #else
519 if (antialias)
520 text_surface=TTF_RenderText_Shaded(font, str, fg_color, bg_color );
521 else
522 text_surface=TTF_RenderText_Solid(font, str, fg_color);
523 #endif
524 if (!text_surface)
525 {
526 TTF_CloseFont(font);
527 return NULL;
528 }
529
530 new_brush=Surface_to_bytefield(text_surface, NULL);
531 if (!new_brush)
532 {
533 SDL_FreeSurface(text_surface);
534 TTF_CloseFont(font);
535 return NULL;
536 }
537
538 // Import palette
539 Get_SDL_Palette(text_surface->format->palette, palette);
540
541 if (antialias)
542 {
543 int black_col;
544 // Shaded text: X-Swap the color that is pure black with the BG color number,
545 // so that the brush is immediately 'transparent'
546
547 // Find black (c)
548 for (black_col=0; black_col<256; black_col++)
549 {
550 if (palette[black_col].R==0 && palette[black_col].G==0 && palette[black_col].B==0)
551 break;
552 } // If not found: c = 256 = 0 (byte)
553
554 if (black_col != Back_color)
555 {
556 int c;
557 byte colmap[256];
558 // Swap palette entries
559
560 SWAP_BYTES(palette[black_col].R, palette[Back_color].R)
561 SWAP_BYTES(palette[black_col].G, palette[Back_color].G)
562 SWAP_BYTES(palette[black_col].B, palette[Back_color].B)
563
564 // Define a colormap
565 for (c=0; c<256; c++)
566 colmap[c]=c;
567
568 // The swap
569 colmap[black_col]=Back_color;
570 colmap[Back_color]=black_col;
571
572 Remap_general_lowlevel(colmap, new_brush, new_brush, text_surface->w,text_surface->h, text_surface->w);
573
574 // Also, make the BG color in brush palette have same RGB values as
575 // the current BG color : this will help for remaps.
576 palette[Back_color].R=Main.palette[Back_color].R;
577 palette[Back_color].G=Main.palette[Back_color].G;
578 palette[Back_color].B=Main.palette[Back_color].B;
579 }
580 }
581 else
582 {
583 // Solid text: Was rendered as white on black. Now map colors:
584 // White becomes FG color, black becomes BG. 2-color palette.
585 // Exception: if BG==FG, FG will be set to black or white - any different color.
586 long index;
587 byte new_fore=Fore_color;
588
589 if (Fore_color==Back_color)
590 {
591 new_fore=Best_color_perceptual_except(Main.palette[Back_color].R, Main.palette[Back_color].G, Main.palette[Back_color].B, Back_color);
592 }
593
594 for (index=0; index < text_surface->w * text_surface->h; index++)
595 {
596 if (palette[*(new_brush+index)].G < 128)
597 *(new_brush+index)=Back_color;
598 else
599 *(new_brush+index)=new_fore;
600 }
601
602 // Now copy the current palette to brushe's, for consistency
603 // with the indices.
604 memcpy(palette, Main.palette, sizeof(T_Palette));
605
606 }
607 *width=text_surface->w;
608 *height=text_surface->h;
609 SDL_FreeSurface(text_surface);
610 TTF_CloseFont(font);
611 return new_brush;
612 }
613 #endif
614
615 #if defined(WIN32)
Render_text_Win32(const char * str,int font_number,int size,int antialias,int bold,int italic,int * width,int * height,T_Palette palette)616 byte *Render_text_Win32(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height, T_Palette palette)
617 {
618 int str_len;
619 HGDIOBJ oldobj;
620 HGDIOBJ oldfont;
621 RECT rect;
622 BITMAPINFO *bi;
623 HDC dc;
624 HBITMAP bm;
625 SIZE s;
626 byte * pixels = NULL;
627 byte * new_brush = NULL;
628 int i;
629 int x, y;
630 HFONT font;
631 const char * font_name;
632
633 font_name = Font_name(font_number);
634
635 font = CreateFontA(size, 0, 0, 0 /* nOrientation */,
636 bold ? FW_BOLD : FW_REGULAR, italic, 0 /* underline */, 0 /*strikeout */,
637 ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
638 antialias ? ANTIALIASED_QUALITY : NONANTIALIASED_QUALITY /* DEFAULT_QUALITY*/,
639 DEFAULT_PITCH | FF_DONTCARE, font_name);
640 if (font == NULL)
641 return NULL;
642
643 dc = CreateCompatibleDC(NULL);
644 oldfont = SelectObject(dc, font);
645 str_len = (int)strlen(str);
646 if (!GetTextExtentPoint32A(dc, str, str_len, &s))
647 {
648 s.cx = 320;
649 s.cy = 32;
650 }
651
652 bi = (BITMAPINFO*)_alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
653 memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
654 bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
655 bi->bmiHeader.biWidth = (s.cx + 3) & ~3;
656 bi->bmiHeader.biHeight = -s.cy;
657 bi->bmiHeader.biPlanes = 1;
658 bi->bmiHeader.biBitCount = antialias ? 32 : 8; // the GDI does Antialiasing only on TrueColor DIB
659 bi->bmiHeader.biCompression = BI_RGB;
660
661 for (i = 0; i < 256; i++) {
662 bi->bmiColors[i].rgbRed = i;
663 bi->bmiColors[i].rgbGreen = i;
664 bi->bmiColors[i].rgbBlue = i;
665 palette[i].R = i;
666 palette[i].G = i;
667 palette[i].B = i;
668 }
669 bm = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (void **)&pixels, NULL, 0);
670 oldobj = SelectObject(dc, bm);
671
672 SetTextColor(dc, RGB(255,255,255));
673 SetBkColor(dc, RGB(0,0,0));
674 SetBkMode(dc, OPAQUE);
675 rect.left=0;
676 rect.top=0;
677 rect.right = s.cx;
678 rect.bottom = s.cy;
679 DrawTextA(dc, str, str_len, &rect, DT_LEFT | DT_SINGLELINE | DT_NOCLIP | DT_NOPREFIX ) ;
680 GdiFlush();
681 SelectObject(dc, oldobj);
682 SelectObject(dc, oldfont);
683
684 new_brush = (byte *)malloc(s.cx*s.cy);
685 if (antialias)
686 {
687 for (y = 0; y < s.cy; y++)
688 {
689 // get the value from the 1st color component.
690 for (x = 0; x < s.cx; x++)
691 new_brush[x + y * s.cx] = pixels[(x + y * bi->bmiHeader.biWidth) * 4];
692 }
693 }
694 else
695 {
696 for (y = 0; y < s.cy; y++)
697 {
698 for (x = 0; x < s.cx; x++)
699 {
700 byte v = pixels[y*bi->bmiHeader.biWidth+x];
701 new_brush[y*s.cx+x] = (v != 0) ? Fore_color : Back_color;
702 }
703 }
704 memcpy(palette, Main.palette, sizeof(T_Palette));
705 }
706 *width = s.cx;
707 *height = s.cy;
708
709 DeleteObject(bm);
710 ReleaseDC(NULL, dc);
711 DeleteObject(font);
712 return new_brush;
713 }
714 #endif
715
Render_text_SFont(const char * str,int font_number,int * width,int * height,T_Palette palette)716 byte *Render_text_SFont(const char *str, int font_number, int *width, int *height, T_Palette palette)
717 {
718 SFont_Font *font;
719 T_GFX2_Surface * text_surface;
720 T_GFX2_Surface *font_surface;
721 byte * new_brush = NULL;
722
723 // Chargement de la fonte
724 font_surface = Load_surface(Font_name(font_number), NULL, NULL);
725 if (!font_surface)
726 {
727 Verbose_message("Warning", "Error loading font");
728 // TODO this leaves a non-erased cursor when the window closes.
729 return NULL;
730 }
731 font=SFont_InitFont(font_surface);
732 if (!font)
733 {
734 GFX2_Log(GFX2_ERROR, "Font init failed : %s\n", Font_name(font_number));
735 Free_GFX2_Surface(font_surface);
736 return NULL;
737 }
738
739 // Calcul des dimensions
740 *height = SFont_TextHeight(font, str);
741 *width = SFont_TextWidth(font, str);
742
743 text_surface = New_GFX2_Surface(*width, *height);
744 if (text_surface == NULL)
745 {
746 GFX2_Log(GFX2_WARNING, "Failed to allocate text surface\n");
747 SFont_FreeFont(font);
748 return NULL;
749 }
750 // Fill with transparent color
751 memset(text_surface->pixels, font->Transparent, *width * *height);
752 // Rendu du texte
753 SFont_Write(text_surface, font, 0, 0, str);
754
755 // Copy palette
756 memcpy(palette, font_surface->palette, sizeof(T_Palette));
757
758 new_brush = text_surface->pixels; // "Steal" pixels from surface
759
760 // Swap current BG color with font's transparent color
761 if (font->Transparent != Back_color)
762 {
763 int c;
764 byte colmap[256];
765 // Swap palette entries
766
767 SWAP_BYTES(palette[font->Transparent].R, palette[Back_color].R)
768 SWAP_BYTES(palette[font->Transparent].G, palette[Back_color].G)
769 SWAP_BYTES(palette[font->Transparent].B, palette[Back_color].B)
770
771 // Define a colormap
772 for (c=0; c<256; c++)
773 colmap[c]=c;
774
775 // The swap
776 colmap[font->Transparent]=Back_color;
777 colmap[Back_color]=font->Transparent;
778
779 Remap_general_lowlevel(colmap, new_brush, new_brush, text_surface->w, text_surface->h, text_surface->w);
780
781 }
782
783 SFont_FreeFont(font);
784 free(text_surface); // Do not call Free_GFX2_Surface() because pixels was stolen
785
786 return new_brush;
787 }
788
789 // Crée une brosse à partir des paramètres de texte demandés.
790 // Si cela réussit, la fonction place les dimensions dans width et height,
791 // et retourne l'adresse du bloc d'octets.
Render_text(const char * str,int font_number,int size,int antialias,int bold,int italic,int * width,int * height,T_Palette palette)792 byte *Render_text(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height, T_Palette palette)
793 {
794 T_Font *font = font_list_start;
795 int index=font_number;
796 #if defined(NOTTF) && !defined(WIN32)
797 (void) size; // unused
798 (void) antialias; // unused
799 (void) bold; // unused
800 (void) italic; // unused
801 #endif
802
803 // Verification type de la fonte
804 if (font_number < 0 || font == NULL)
805 return NULL;
806
807 while (index--)
808 {
809 font = font->Next;
810 if (font == NULL)
811 return NULL;
812 }
813 if (font->Is_truetype)
814 {
815 #if !defined(NOTTF)
816 return Render_text_TTF(str, font_number, size, antialias, bold, italic, width, height, palette);
817 #elif defined(WIN32)
818 return Render_text_Win32(str, font_number, size, antialias, bold, italic, width, height, palette);
819 #else
820 return NULL;
821 #endif
822 }
823 else
824 {
825 return Render_text_SFont(str, font_number, width, height, palette);
826 }
827 }
828