1 /**
2 * Fonts
3
4 * Copyright (C) 2007, 2008, 2009 Sylvain Beucler
5
6 * This file is part of GNU FreeDink
7
8 * GNU FreeDink is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 3 of the
11 * License, or (at your option) any later version.
12
13 * GNU FreeDink is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
28 #define WIN32_LEAN_AND_MEAN
29 #define _WIN32_IE 0x0401
30 #include <windows.h>
31 #include <shlobj.h>
32 #endif
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <errno.h>
37 #include "SDL.h"
38 #include "SDL_ttf.h"
39 #include "dinkvar.h"
40 #include "gfx.h"
41 #include "io_util.h"
42 #include "paths.h"
43 #include "gfx_fonts.h"
44 #include "gfx_palette.h"
45 #include "vgasys_fon.h"
46 #include "init.h"
47 #include "log.h"
48
49
50 /* Default size was 18 in the original game, but it refers to a
51 different part of the font glyph (see doc/fonts.txt for
52 details). 16 matches that size with SDL_ttf (possibly only for
53 LiberationSans). */
54 #define FONT_SIZE 16
55
56 /* Default fonts: dialog and system */
57 static TTF_Font *dialog_font = NULL;
58 static TTF_Font *system_font = NULL;
59
60 /* Current font parameters */
61 static SDL_Color text_color;
62
63 static TTF_Font *load_default_font();
64 static void setup_font(TTF_Font *font);
65
66 // D-Mod-defined font colors
67 struct font_color
68 {
69 int red;
70 int green;
71 int blue;
72 };
73 static struct font_color font_colors[16];
74
75 #ifdef HAVE_FONTCONFIG
76 #include <fontconfig/fontconfig.h>
77 /* Get filename for canonical font name 'fontname'. Return NULL if the
78 font cannot be found (for correctness, no alternate font will be
79 provided). */
get_fontconfig_path(char * fontname)80 char* get_fontconfig_path(char* fontname)
81 {
82 char* filename = NULL;
83 FcPattern* p = NULL;
84 FcChar8* strval = NULL;
85 FcObjectSet *attr = NULL;
86
87 if (!FcInit())
88 {
89 log_error("get_fontconfig_path: cannot initialize fontconfig");
90 return NULL;
91 }
92
93 p = FcNameParse((FcChar8*)fontname);
94 if (p == NULL)
95 {
96 log_error("get_fontconfig_path: invalid font pattern: %s", fontname);
97 return NULL;
98 }
99 /* Grab filename attribute */
100 attr = FcObjectSetBuild (FC_FILE, (char *) 0);
101
102 FcFontSet *fs = FcFontList (0, p, attr);
103 if (fs->nfont == 0)
104 {
105 log_error("get_fontconfig_path: no matching font for %s", fontname);
106 return NULL;
107 }
108 if (FcPatternGetString(fs->fonts[0], FC_FILE, 0, &strval) == FcResultTypeMismatch
109 || strval == NULL)
110 {
111 log_error("get_fontconfig_path: cannot find font filename for %s", fontname);
112 return NULL;
113 }
114
115 filename = strdup((char*)strval);
116
117 FcFontSetDestroy(fs);
118 FcObjectSetDestroy(attr);
119 FcPatternDestroy(p);
120 FcFini();
121
122 return filename;
123 }
124 #endif
125
126 /**
127 * Init font subsystem and one built-in font, so we can display error
128 * messages in emergency (init error) situations
129 */
gfx_fonts_init_failsafe()130 int gfx_fonts_init_failsafe()
131 {
132 if (!TTF_WasInit() && TTF_Init() == -1)
133 return -1;
134
135 /* Load system font from compiled data */
136 if (system_font == NULL)
137 {
138 system_font = TTF_OpenFontRW(SDL_RWFromConstMem(vgasys_fon, sizeof(vgasys_fon)),
139 1, FONT_SIZE);
140 if (system_font == NULL)
141 return -1;
142 setup_font(system_font);
143 }
144
145 return 0;
146 }
147
148 /**
149 * Init font subsystem and load the default fonts
150 */
gfx_fonts_init()151 int gfx_fonts_init()
152 {
153 if (TTF_Init() == -1) {
154 init_set_error_msg(TTF_GetError());
155 return -1;
156 }
157
158 /* Load system font from compiled data */
159 system_font = TTF_OpenFontRW(SDL_RWFromConstMem(vgasys_fon, sizeof(vgasys_fon)),
160 1, FONT_SIZE);
161 if (system_font == NULL)
162 {
163 init_set_error_msg("Failed to load builtin 'vgasys.fon' font.");
164 return -1;
165 }
166 setup_font(system_font);
167
168 /* Load dialog font from built-in resources */
169 dialog_font = load_default_font();
170 if (dialog_font == NULL)
171 return -1; /* error message set by load_default_font */
172 setup_font(dialog_font);
173
174 gfx_fonts_init_colors();
175
176 return 0;
177 }
178
179 /**
180 * Quit the font subsystem (and free loaded fonts from memory)
181 */
gfx_fonts_quit(void)182 void gfx_fonts_quit(void)
183 {
184 if (dialog_font != NULL)
185 {
186 TTF_CloseFont(dialog_font);
187 dialog_font = NULL;
188 }
189 if (system_font != NULL)
190 {
191 // Uncomment when FreeType 2.5.3 is widespread
192 // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=747002
193 //TTF_CloseFont(system_font);
194 system_font = NULL;
195 }
196
197 TTF_Quit();
198 }
199
200
201 /**
202 * Default font from resources and pkgdatadir
203 */
load_default_font()204 static TTF_Font *load_default_font() {
205 TTF_Font *font_object = NULL;
206 SDL_RWops* rwops = NULL;
207
208 /* Try from resources */
209 if (rwops == NULL)
210 {
211 rwops = find_resource_as_rwops("LiberationSans-Regular.ttf");
212 }
213 #ifdef HAVE_FONTCONFIG
214 if (rwops == NULL)
215 {
216 char *path = get_fontconfig_path("Liberation Sans:style=Regular");
217 rwops = SDL_RWFromFile(path, "rb");
218 free(path);
219 }
220 #endif
221 if (rwops == NULL)
222 {
223 init_set_error_msg("Could not open font 'LiberationSans-Regular.ttf'. I tried:\n"
224 "- loading from '%s'\n"
225 "- loading from '%s'\n"
226 "- loading from '%s'\n"
227 "- loading from executable's resources\n"
228 #ifdef HAVE_FONTCONFIG
229 "- querying fontconfig"
230 #endif
231 ,
232 paths_getpkgdatadir(), paths_getdefaultpkgdatadir(), paths_getexedir());
233 return NULL;
234 }
235
236 font_object = TTF_OpenFontRW(rwops, 1, FONT_SIZE);
237 if (font_object == NULL)
238 {
239 init_set_error_msg("Could not open font 'LiberationSans-Regular.ttf': %s", TTF_GetError());
240 return NULL;
241 }
242
243 return font_object;
244 }
245
246 /**
247 * Change the current dialog font (DinkC initfont() command)
248 */
initfont(char * fontname)249 int initfont(char* fontname) {
250 TTF_Font *new_font = NULL;
251 char* ext = ".ttf";
252 char* filename = malloc(strlen(fontname) + strlen(ext) + 1);
253 strcpy(filename, fontname);
254 strcat(filename, ext);
255
256 if (new_font == NULL)
257 {
258 char *path = NULL;
259 #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
260 /* Look in system fonts dir */
261 path = malloc(MAX_PATH + 1 + strlen(filename) + 1);
262 /* C:\WINNT\Fonts */
263 SHGetSpecialFolderPath(NULL, path, CSIDL_FONTS, 0);
264 strcat(path, "\\");
265 strcat(path, filename);
266 #else
267 # ifdef HAVE_FONTCONFIG
268 path = get_fontconfig_path(fontname);
269 # else
270 path = NULL;
271 # endif
272 #endif
273 if (path == NULL)
274 {
275 log_error("initfont: cannot find '%s'", fontname);
276 }
277 else
278 {
279 new_font = TTF_OpenFont(path, FONT_SIZE);
280 if (new_font == NULL)
281 log_error("TTF_OpenFont: %s", TTF_GetError());
282 free(path);
283 }
284 }
285
286 if (new_font == NULL)
287 return -1;
288
289
290 /* new_font could be loaded - we can free the previous one */
291 TTF_CloseFont(dialog_font);
292 dialog_font = new_font;
293
294 setup_font(dialog_font);
295
296 return 0;
297 }
298
299 /**
300 * Change a font color (DinkC set_font_color() command)
301 */
set_font_color(int no,int red,int green,int blue)302 void set_font_color(int no, int red, int green, int blue)
303 {
304 if (no >= 1 && no <= 15
305 && red >= 0 && red <= 255
306 && green >= 0 && green <= 255
307 && blue >= 0 && blue <= 255)
308 {
309 font_colors[no].red = red;
310 font_colors[no].green = green;
311 font_colors[no].blue = blue;
312 }
313 }
314
315
316 /**
317 * Apply default style to the font
318 * Plus some informative output
319 */
320 static void
setup_font(TTF_Font * font)321 setup_font(TTF_Font *font)
322 {
323 char *familyname = TTF_FontFaceFamilyName(font);
324 if(familyname)
325 log_info("The family name of the face in the font is: %s", familyname);
326 char *stylename = TTF_FontFaceStyleName(font);
327 if(stylename)
328 log_info("The name of the face in the font is: %s", stylename);
329 log_info("The font max height is: %d", TTF_FontHeight(font));
330 log_info("The font ascent is: %d", TTF_FontAscent(font));
331 log_info("The font descent is: %d", TTF_FontDescent(font));
332 log_info("The font line skip is: %d", TTF_FontLineSkip(font));
333 if(TTF_FontFaceIsFixedWidth(font))
334 log_info("The font is fixed width.");
335 else
336 log_info("The font is not fixed width.");
337
338 TTF_SetFontStyle(font, TTF_STYLE_BOLD);
339 }
340
341
342
343
FONTS_SetTextColor(Uint8 r,Uint8 g,Uint8 b)344 void FONTS_SetTextColor(Uint8 r, Uint8 g, Uint8 b) {
345 text_color.r = r;
346 text_color.g = g;
347 text_color.b = b;
348 }
FONTS_SetTextColorIndex(int no)349 void FONTS_SetTextColorIndex(int no) {
350 text_color.r = font_colors[no].red;
351 text_color.g = font_colors[no].green;
352 text_color.b = font_colors[no].blue;
353 }
354
355
356 static void
print_text(TTF_Font * font,char * str,int x,int y,int w,SDL_Color color,int hcenter)357 print_text (TTF_Font * font, char *str, int x, int y, int w, SDL_Color /*&*/color,
358 /*bool*/int hcenter)
359 {
360 int new_x, text_w, text_h;
361 SDL_Surface *tmp;
362 SDL_Rect dst;
363
364 if (strlen (str) == 0)
365 return;
366
367 /* Msg (("printing \"%s\"", str)); */
368
369
370 /* Rationale: text color is not affected by palette shifts (yellow
371 stays yellow even if we're using the negative palette from Lyna's
372 story) _but_ text color is the closest one in the final palette
373 color (so when after a fade_down(), the available colors are only
374 black and white, yellow becomes white, as yellow is just not
375 available, and white is closest than black). */
376 /* So we get the color index from cur_screen_palette (final color
377 even after palette effects), and use the color value from
378 GFX_real_pal (reference palette used for all graphics before
379 palette effects). */
380 /* Previously this was implemented using BlitSurface palette
381 conversion (commit 2007-11-01) but this was terribly slow (full
382 palette conversion done 5 times per text (for the border effect)
383 and per frame). */
384 if (!truecolor)
385 {
386 SDL_PixelFormat fmt;
387 SDL_Palette pal;
388 pal.ncolors = 256;
389 SDL_Color tmppal[256];
390 gfx_palette_get_phys(tmppal);
391 pal.colors = tmppal;
392 fmt.palette = &pal;
393 Uint32 phys_index = SDL_MapRGB(&fmt, color.r, color.g, color.b);
394 SDL_GetRGB(phys_index, GFX_lpDDSBack->format, &(color.r), &(color.g), &(color.b));
395 }
396
397 /* Transparent, low quality - closest to the original engine. */
398 /* Besides, we do need a monochrome render, since we're doing nasty
399 tricks to set the color appropriately */
400 tmp = TTF_RenderUTF8_Solid(font, str, color);
401
402 /* Bigger, with a box background */
403 // SDL_Color background = {0, 0, 0};
404 // tmp = TTF_RenderText_Shaded(font, str, color, background);
405
406 /* High quality, 32bit+alpha, but I can't get the transparency
407 OK. Directly applying it on lpDDSBack messed with the colors of
408 the graphics behind the text, and trying to pre-convert it by
409 blitting it on a transparent surface missed some of the text
410 borders in the final result (i.e. multiple calls to print_text
411 with a small postponement to make the borders). */
412 // tmp = TTF_RenderText_Blended(font, str, color);
413 // {
414 // // SDL_Surface *conv = SDL_DisplayFormat(tmp);
415 // SDL_Surface *conv = SDL_CreateRGBSurface(SDL_SWSURFACE, tmp->w, tmp->h, 8,
416 // 0, 0, 0, 0);
417 // SDL_SetPalette(conv, SDL_LOGPAL, GFX_real_pal, 0, 256);
418 // SDL_SetColorKey(conv, SDL_SRCCOLORKEY, 0);
419 // SDL_FillRect(conv, NULL, 0);
420 // SDL_BlitSurface(tmp, NULL, conv, NULL);
421 // SDL_FreeSurface(tmp);
422 // tmp = conv;
423 // }
424
425 if (tmp == NULL)
426 {
427 log_error("Error rendering text: %s; font is %p", TTF_GetError(), font);
428 return;
429 }
430
431 TTF_SizeUTF8 (font, str, &text_w, &text_h);
432 new_x = x;
433 if (hcenter)
434 {
435 new_x += w / 2;
436 new_x -= text_w / 2;
437 }
438 dst.x = new_x; dst.y = y;
439
440 SDL_Rect src;
441 src.x = src.y = 0;
442 src.w = w; // truncate text if outside the box
443 src.h = tmp->h;
444 SDL_BlitSurface(tmp, &src, GFX_lpDDSBack, &dst);
445
446 SDL_FreeSurface (tmp);
447 }
448
449 /**
450 * Get the size in pixel of 'len' chars starting at 'str'
451 */
452 static int
font_len(TTF_Font * font,char * str,int len)453 font_len (TTF_Font *font, char *str, int len)
454 {
455 int text_w;
456 char *tmp;
457
458 /* Get the specified string portion and terminate it by \0 */
459 tmp = (char *) malloc ((len + 1) * sizeof (char));
460 strncpy (tmp, str, len);
461 tmp[len] = 0;
462
463 TTF_SizeUTF8 (font, tmp, &text_w, NULL);
464 free (tmp);
465
466 return text_w;
467 }
468
469 /**
470 * Add newlines in the text so that it fit in 'box'
471 * (a.k.a. word-wrapping)
472 */
473 static int
process_text_for_wrapping(TTF_Font * font,char * str,int max_len)474 process_text_for_wrapping (TTF_Font *font, char *str, int max_len)
475 {
476 //printf("process_text_for_wrapping: %s on %dx%d\n", str, box->right - box->left, box->bottom - box->top);
477 int i, start, line, last_fit;
478
479 start = 0;
480 i = 0;
481 last_fit = -1;
482 line = 0;
483 while (str[i] != '\0')
484 {
485 int len;
486
487 /* Skip forward to the end of the word */
488 while (str[i] != '\0' && str[i] != ' ' && str[i] != '\n')
489 i++;
490
491 /* If the length of the text from start to i is bigger than the
492 box, then draw the text up to the last fitting portion -
493 unless that was the beginning of the string. */
494 len = font_len (font, &str[start], i - start);
495
496 if (len > max_len)
497 {
498 /* String is bigger than the textbox */
499
500 if (last_fit == -1)
501 {
502 /* Current word is too long by itself already, let's
503 keep it on a single line */
504 if (str[i] != '\0')
505 str[i] = '\n';
506 /* continue on a new line */
507 line++;
508 start = i + 1;
509 if (str[i] != '\0')
510 i++;
511 }
512 else
513 {
514 /* All those words is bigger than the textbox, linebreak
515 at previous space */
516 str[last_fit] = '\n';
517 /* continue on a new line */
518 line++;
519 start = last_fit + 1;
520 i = last_fit + 1;
521 }
522 last_fit = -1;
523 }
524 else if (str[i] == '\0')
525 {
526 line++;
527 }
528 else if (str[i] == '\n')
529 {
530 line++;
531 i++;
532 start = i;
533 last_fit = -1;
534 }
535 else
536 {
537 last_fit = i;
538 i++;
539 }
540 }
541
542 return line;
543 }
544
545 /**
546 * Print text 'str' in 'box', adding newlines if necessary
547 * (word-wrapping). Return the text height in pixels.
548 *
549 * calc_only: don't actually draw text on screen, but still compute
550 * the text height
551 */
552 int
print_text_wrap(char * str,rect * box,int hcenter,int calc_only,FONT_TYPE font_type)553 print_text_wrap (char *str, rect* box,
554 /*bool*/int hcenter, int calc_only, FONT_TYPE font_type)
555 {
556 int x, y, res_height;
557 char *tmp, *pline, *pc;
558 int this_is_last_line = 0;
559 // SDL_Color color = {0, 0, 0};
560 SDL_Color color = text_color;
561 TTF_Font *font;
562 int lineskip = 0;
563
564 if (font_type == FONT_DIALOG)
565 font = dialog_font;
566 else if (font_type == FONT_SYSTEM)
567 font = system_font;
568 else
569 {
570 log_error("Error: unknown font type %d", font_type);
571 exit(1);
572 }
573
574 /* Workaround: with vgasys.fon, lineskip is always 1. We'll use it's
575 height instead. */
576 lineskip = TTF_FontLineSkip(font);
577 if (lineskip == 1)
578 lineskip = TTF_FontHeight(font);
579
580 tmp = strdup(str);
581 process_text_for_wrapping(font, tmp, box->right - box->left);
582
583 x = box->left;
584 y = box->top;
585
586 res_height = 0;
587 pline = pc = tmp;
588 this_is_last_line = 0;
589 while (!this_is_last_line)
590 {
591 while (*pc != '\n' && *pc != '\0')
592 pc++;
593
594 if (*pc == '\0')
595 this_is_last_line = 1;
596 else
597 /* Terminate the current line to feed it to print_text */
598 *pc= '\0';
599
600 if (!calc_only)
601 print_text(font, pline, x, y + res_height, (box->right - box->left), color, hcenter);
602
603 res_height += lineskip;
604
605 /* advance to next line*/
606 pc++;
607 pline = pc;
608 }
609 free(tmp);
610 return res_height;
611 }
612
613
614 /**
615 * Display text for debug mode (with a white background)
616 */
617 void
print_text_wrap_debug(char * text,int x,int y)618 print_text_wrap_debug(char *text, int x, int y)
619 {
620 char *tmp, *pline, *pc;
621 int this_is_last_line = 0;
622 int res_height = 0;
623 SDL_Color bgcolor = {255, 255, 255};
624 int max_len = 640;
625
626 /* Workaround: with vgasys.fon, lineskip is always 1. We'll use it's
627 height instead. */
628 int lineskip = TTF_FontHeight(system_font);
629
630 int textlen = strlen(text);
631 tmp = malloc(strlen(text) + 1);
632 /* drop '\r' */
633 pc = tmp;
634 int i;
635 for (i = 0; i < textlen; i++)
636 if (text[i] == '\r' && text[i+1] == '\n')
637 continue;
638 else
639 *(pc++) = text[i];
640 *pc = '\0';
641
642 process_text_for_wrapping(system_font, tmp, max_len);
643
644 pline = pc = tmp;
645 this_is_last_line = 0;
646 while (!this_is_last_line)
647 {
648 while (*pc != '\n' && *pc != '\0')
649 pc++;
650
651 if (*pc == '\0')
652 this_is_last_line = 1;
653 else
654 /* Terminate the current line to feed it to print_text */
655 *pc= '\0';
656
657 SDL_Rect dst = {x, y + res_height, -1, -1};
658 SDL_Surface *rendered_text = TTF_RenderUTF8_Shaded(system_font, pline, text_color, bgcolor);
659 SDL_BlitSurface(rendered_text, NULL, GFX_lpDDSBack, &dst);
660 SDL_FreeSurface(rendered_text);
661
662 res_height += lineskip;
663
664 /* advance to next line*/
665 pc++;
666 pline = pc;
667 }
668 free(tmp);
669 }
670
671
672
673 /* Say, SaySmall: only used by freedinkedit.c */
674 /**
675 * SaySmall: print text in a 40x40 small square; without font border
676 * (sprite info boxes when typing 'I', plus something in tile
677 * hardness)
678 */
SaySmall(char thing[500],int px,int py,int r,int g,int b)679 void SaySmall(char thing[500], int px, int py, int r, int g, int b)
680 {
681 rect rcRect;
682 /* HDC hdc; */
683 /* if (lpDDSBack->GetDC(&hdc) == DD_OK) */
684 /* { */
685 /* SetBkMode(hdc, TRANSPARENT); */
686 rect_set(&rcRect,px,py,px+40,py+40);
687 /* SetTextColor(hdc,RGB(r,g,b)); */
688 /* DrawText(hdc,thing,lstrlen(thing),&rcRect,DT_WORDBREAK); */
689 // FONTS
690 FONTS_SetTextColor(r, g, b);
691 print_text_wrap(thing, &rcRect, 0, 0, FONT_SYSTEM);
692
693 /* lpDDSBack->ReleaseDC(hdc); */
694 /* } */
695 }
696 /**
697 * Say: print text until it reaches the border of the screen, with a
698 * font border (input dialog boxes)
699 */
Say(char thing[500],int px,int py)700 void Say(char thing[500], int px, int py)
701 {
702 rect rcRect;
703 /* HDC hdc; */
704
705 /* if (lpDDSBack->GetDC(&hdc) == DD_OK) */
706 /* { */
707 /* SetBkMode(hdc, TRANSPARENT); */
708 rect_set(&rcRect,px,py,620,480);
709 /* SelectObject (hdc, hfont_small); */
710
711 /* SetTextColor(hdc,RGB(8,14,21)); */
712 /* DrawText(hdc,thing,lstrlen(thing),&rcRect,DT_WORDBREAK); */
713 // FONTS
714 FONTS_SetTextColor(8, 14, 21);
715 print_text_wrap(thing, &rcRect, 0, 0, FONT_DIALOG);
716
717 rect_offset(&rcRect,-2,-2);
718 /* DrawText(hdc,thing,lstrlen(thing),&rcRect,DT_WORDBREAK); */
719 // FONTS
720 print_text_wrap(thing, &rcRect, 0, 0, FONT_DIALOG);
721
722 rect_offset(&rcRect,1,1);
723 /* SetTextColor(hdc,RGB(255,255,0)); */
724 /* DrawText(hdc,thing,lstrlen(thing),&rcRect,DT_WORDBREAK); */
725 // FONTS
726 FONTS_SetTextColor(255, 255, 0);
727 print_text_wrap(thing, &rcRect, 0, 0, FONT_DIALOG);
728
729 /* lpDDSBack->ReleaseDC(hdc); */
730 /* } */
731 }
732
733
gfx_fonts_init_colors()734 void gfx_fonts_init_colors()
735 {
736 //Light Magenta
737 font_colors[1].red = 255;
738 font_colors[1].green = 198;
739 font_colors[1].blue = 255;
740
741 //Dark Green
742 font_colors[2].red = 131;
743 font_colors[2].green = 181;
744 font_colors[2].blue = 74;
745
746 //Bold Cyan
747 font_colors[3].red = 99;
748 font_colors[3].green = 242;
749 font_colors[3].blue = 247;
750
751 //Orange
752 font_colors[4].red = 255;
753 font_colors[4].green = 156;
754 font_colors[4].blue = 74;
755
756 //Magenta
757 font_colors[5].red = 222;
758 font_colors[5].green = 173;
759 font_colors[5].blue = 255;
760
761 //Brown Orange
762 font_colors[6].red = 244;
763 font_colors[6].green = 188;
764 font_colors[6].blue = 73;
765
766 //Light Gray
767 font_colors[7].red = 173;
768 font_colors[7].green = 173;
769 font_colors[7].blue = 173;
770
771 //Dark Gray
772 font_colors[8].red = 85;
773 font_colors[8].green = 85;
774 font_colors[8].blue = 85;
775
776 //Sky Blue
777 font_colors[9].red = 148;
778 font_colors[9].green = 198;
779 font_colors[9].blue = 255;
780
781 //Bright Green
782 font_colors[10].red = 0;
783 font_colors[10].green = 255;
784 font_colors[10].blue = 0;
785
786 //Yellow
787 font_colors[11].red = 255;
788 font_colors[11].green = 255;
789 font_colors[11].blue = 2;
790
791 //Yellow
792 font_colors[12].red = 255;
793 font_colors[12].green = 255;
794 font_colors[12].blue = 2;
795
796 //Hot Pink
797 font_colors[13].red = 255;
798 font_colors[13].green = 132;
799 font_colors[13].blue = 132;
800
801 //Yellow
802 font_colors[14].red = 255;
803 font_colors[14].green = 255;
804 font_colors[14].blue = 2;
805
806 //White
807 font_colors[15].red = 255;
808 font_colors[15].green = 255;
809 font_colors[15].blue = 255;
810 }
811