1 /* FreeType 2 and UTF-8 encoding support for
8 #include "ft2_fontdefs.h"
10 static int img_fontmap[256] = {
11 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
12 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
13 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // shift+digit line
14 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // digits
15 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // caps
16 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // caps
17 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // small
18 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // small
19 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // specials
20 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // faces
21 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
25 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
26 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
30 ================================================================================
31 CVars introduced with the freetype extension
32 ================================================================================
35 cvar_t r_font_disable_freetype = {CVAR_SAVE, "r_font_disable_freetype", "1", "disable freetype support for fonts entirely"};
36 cvar_t r_font_use_alpha_textures = {CVAR_SAVE, "r_font_use_alpha_textures", "0", "use alpha-textures for font rendering, this should safe memory"};
37 cvar_t r_font_size_snapping = {CVAR_SAVE, "r_font_size_snapping", "1", "stick to good looking font sizes whenever possible - bad when the mod doesn't support it!"};
38 cvar_t r_font_hinting = {CVAR_SAVE, "r_font_hinting", "3", "0 = no hinting, 1 = light autohinting, 2 = full autohinting, 3 = full hinting"};
39 cvar_t r_font_antialias = {CVAR_SAVE, "r_font_antialias", "1", "0 = monochrome, 1 = grey" /* , 2 = rgb, 3 = bgr" */};
40 cvar_t developer_font = {CVAR_SAVE, "developer_font", "0", "prints debug messages about fonts"};
43 ================================================================================
44 Function definitions. Taken from the freetype2 headers.
45 ================================================================================
50 (*qFT_Init_FreeType)( FT_Library *alibrary );
52 (*qFT_Done_FreeType)( FT_Library library );
55 (*qFT_New_Face)( FT_Library library,
56 const char* filepathname,
61 (*qFT_New_Memory_Face)( FT_Library library,
62 const FT_Byte* file_base,
67 (*qFT_Done_Face)( FT_Face face );
69 (*qFT_Select_Size)( FT_Face face,
70 FT_Int strike_index );
72 (*qFT_Request_Size)( FT_Face face,
73 FT_Size_Request req );
75 (*qFT_Set_Char_Size)( FT_Face face,
76 FT_F26Dot6 char_width,
77 FT_F26Dot6 char_height,
78 FT_UInt horz_resolution,
79 FT_UInt vert_resolution );
81 (*qFT_Set_Pixel_Sizes)( FT_Face face,
83 FT_UInt pixel_height );
85 (*qFT_Load_Glyph)( FT_Face face,
87 FT_Int32 load_flags );
89 (*qFT_Load_Char)( FT_Face face,
91 FT_Int32 load_flags );
93 (*qFT_Get_Char_Index)( FT_Face face,
96 (*qFT_Render_Glyph)( FT_GlyphSlot slot,
97 FT_Render_Mode render_mode );
99 (*qFT_Get_Kerning)( FT_Face face,
103 FT_Vector *akerning );
104 FT_EXPORT( FT_Error )
105 (*qFT_Attach_Stream)( FT_Face face,
106 FT_Open_Args* parameters );
108 ================================================================================
109 Support for dynamically loading the FreeType2 library
110 ================================================================================
113 static dllfunction_t ft2funcs[] =
115 {"FT_Init_FreeType", (void **) &qFT_Init_FreeType},
116 {"FT_Done_FreeType", (void **) &qFT_Done_FreeType},
117 //{"FT_New_Face", (void **) &qFT_New_Face},
118 {"FT_New_Memory_Face", (void **) &qFT_New_Memory_Face},
119 {"FT_Done_Face", (void **) &qFT_Done_Face},
120 {"FT_Select_Size", (void **) &qFT_Select_Size},
121 {"FT_Request_Size", (void **) &qFT_Request_Size},
122 {"FT_Set_Char_Size", (void **) &qFT_Set_Char_Size},
123 {"FT_Set_Pixel_Sizes", (void **) &qFT_Set_Pixel_Sizes},
124 {"FT_Load_Glyph", (void **) &qFT_Load_Glyph},
125 {"FT_Load_Char", (void **) &qFT_Load_Char},
126 {"FT_Get_Char_Index", (void **) &qFT_Get_Char_Index},
127 {"FT_Render_Glyph", (void **) &qFT_Render_Glyph},
128 {"FT_Get_Kerning", (void **) &qFT_Get_Kerning},
129 {"FT_Attach_Stream", (void **) &qFT_Attach_Stream},
133 /// Handle for FreeType2 DLL
134 static dllhandle_t ft2_dll = NULL;
136 /// Memory pool for fonts
137 static mempool_t *font_mempool= NULL;
138 static rtexturepool_t *font_texturepool = NULL;
140 /// FreeType library handle
141 static FT_Library font_ft2lib = NULL;
147 Unload the FreeType2 DLL
150 void Font_CloseLibrary (void)
153 Mem_FreePool(&font_mempool);
154 if (font_texturepool)
155 R_FreeTexturePool(&font_texturepool);
156 if (font_ft2lib && qFT_Done_FreeType)
158 qFT_Done_FreeType(font_ft2lib);
161 Sys_UnloadLibrary (&ft2_dll);
168 Try to load the FreeType2 DLL
171 qboolean Font_OpenLibrary (void)
173 const char* dllnames [] =
177 #elif defined(MACOSX)
186 if (r_font_disable_freetype.integer)
194 if (!Sys_LoadLibrary (dllnames, &ft2_dll, ft2funcs))
203 Initialize the freetype2 font subsystem
207 void font_start(void)
209 if (!Font_OpenLibrary())
212 if (qFT_Init_FreeType(&font_ft2lib))
214 Con_Print("ERROR: Failed to initialize the FreeType2 library!\n");
219 font_mempool = Mem_AllocPool("FONT", 0, NULL);
222 Con_Print("ERROR: Failed to allocate FONT memory pool!\n");
227 font_texturepool = R_AllocTexturePool();
228 if (!font_texturepool)
230 Con_Print("ERROR: Failed to allocate FONT texture pool!\n");
236 void font_shutdown(void)
239 for (i = 0; i < MAX_FONTS; ++i)
243 Font_UnloadFont(dp_fonts[i].ft2);
244 dp_fonts[i].ft2 = NULL;
250 void font_newmap(void)
256 Cvar_RegisterVariable(&r_font_disable_freetype);
257 Cvar_RegisterVariable(&r_font_use_alpha_textures);
258 Cvar_RegisterVariable(&r_font_size_snapping);
259 Cvar_RegisterVariable(&r_font_hinting);
260 Cvar_RegisterVariable(&r_font_antialias);
261 Cvar_RegisterVariable(&developer_font);
265 ================================================================================
266 Implementation of a more or less lazy font loading and rendering code.
267 ================================================================================
270 #include "ft2_fontdefs.h"
272 ft2_font_t *Font_Alloc(void)
276 return Mem_Alloc(font_mempool, sizeof(ft2_font_t));
279 qboolean Font_Attach(ft2_font_t *font, ft2_attachment_t *attachment)
281 ft2_attachment_t *na;
283 font->attachmentcount++;
284 na = (ft2_attachment_t*)Mem_Alloc(font_mempool, sizeof(font->attachments[0]) * font->attachmentcount);
287 if (font->attachments && font->attachmentcount > 1)
289 memcpy(na, font->attachments, sizeof(font->attachments[0]) * (font->attachmentcount - 1));
290 Mem_Free(font->attachments);
292 memcpy(na + sizeof(font->attachments[0]) * (font->attachmentcount - 1), attachment, sizeof(*attachment));
293 font->attachments = na;
297 static float Font_VirtualToRealSize(float sz)
303 vw = ((vid.width > 0) ? vid.width : vid_width.value);
304 vh = ((vid.height > 0) ? vid.height : vid_height.value);
305 // now try to scale to our actual size:
306 sn = sz * vh / vid_conheight.value;
308 if ( sn - (float)si >= 0.5 )
313 static qboolean Font_LoadFile(const char *name, int _face, ft2_font_t *font);
314 static qboolean Font_LoadSize(ft2_font_t *font, float size, qboolean no_texture, qboolean no_kerning);
315 qboolean Font_LoadFont(const char *name, dp_font_t *dpfnt)
318 ft2_font_t *ft2, *fbfont, *fb;
327 // check if a fallback font has been specified, if it has been, and the
328 // font fails to load, use the image font as main font
329 for (i = 0; i < MAX_FONT_FALLBACKS; ++i)
331 if (dpfnt->fallbacks[i][0])
335 if (!Font_LoadFile(name, dpfnt->req_face, ft2))
337 if (i >= MAX_FONT_FALLBACKS)
343 strlcpy(ft2->name, name, sizeof(ft2->name));
344 ft2->image_font = true;
345 ft2->has_kerning = false;
349 ft2->image_font = false;
352 // attempt to load fallback fonts:
354 for (i = 0; i < MAX_FONT_FALLBACKS; ++i)
356 if (!dpfnt->fallbacks[i][0])
358 if (! (fb = Font_Alloc()) )
360 Con_Printf("Failed to allocate font for fallback %i of font %s\n", i, name);
363 if (!Font_LoadFile(dpfnt->fallbacks[i], dpfnt->fallback_faces[i], fb))
365 Con_Printf("Failed to allocate font for fallback %i of font %s\n", i, name);
370 for (s = 0; s < MAX_FONT_SIZES; ++s)
372 if (Font_LoadSize(fb, Font_VirtualToRealSize(dpfnt->req_sizes[s]), true, false))
377 Con_Printf("Failed to allocate font for fallback %i of font %s\n", i, name);
382 // at least one size of the fallback font loaded successfully
388 if (fbfont == ft2 && ft2->image_font)
390 // no fallbacks were loaded successfully:
397 for (s = 0; s < MAX_FONT_SIZES; ++s)
399 if (Font_LoadSize(ft2, Font_VirtualToRealSize(dpfnt->req_sizes[s]), false, false))
404 // loading failed for every requested size
405 Font_UnloadFont(ft2);
411 //Con_Printf("%i sizes loaded\n", count);
416 static qboolean Font_LoadFile(const char *name, int _face, ft2_font_t *font)
419 char filename[MAX_QPATH];
423 fs_offset_t datasize;
425 memset(font, 0, sizeof(*font));
427 if (!Font_OpenLibrary())
429 if (!r_font_disable_freetype.integer)
431 Con_Printf("WARNING: can't open load font %s\n"
432 "You need the FreeType2 DLL to load font files\n",
438 namelen = strlen(name);
440 memcpy(filename, name, namelen);
441 memcpy(filename + namelen, ".ttf", 5);
442 data = FS_LoadFile(filename, font_mempool, false, &datasize);
445 memcpy(filename + namelen, ".otf", 5);
446 data = FS_LoadFile(filename, font_mempool, false, &datasize);
450 ft2_attachment_t afm;
452 memcpy(filename + namelen, ".pfb", 5);
453 data = FS_LoadFile(filename, font_mempool, false, &datasize);
457 memcpy(filename + namelen, ".afm", 5);
458 afm.data = FS_LoadFile(filename, font_mempool, false, &afm.size);
461 Font_Attach(font, &afm);
467 // FS_LoadFile being not-quiet should print an error :)
470 Con_Printf("Loading font %s face %i...\n", filename, _face);
472 status = qFT_New_Memory_Face(font_ft2lib, (FT_Bytes)data, datasize, _face, (FT_Face*)&font->face);
473 if (status && _face != 0)
475 Con_Printf("Failed to load face %i of %s. Falling back to face 0\n", _face, name);
477 status = qFT_New_Memory_Face(font_ft2lib, (FT_Bytes)data, datasize, 0, (FT_Face*)&font->face);
481 Con_Printf("ERROR: can't create face for %s\n"
482 "Error %i\n", // TODO: error strings
484 Font_UnloadFont(font);
488 // add the attachments
489 for (i = 0; i < font->attachmentcount; ++i)
492 memset(&args, 0, sizeof(args));
493 args.flags = FT_OPEN_MEMORY;
494 args.memory_base = (const FT_Byte*)font->attachments[i].data;
495 args.memory_size = font->attachments[i].size;
496 if (qFT_Attach_Stream(font->face, &args))
497 Con_Printf("Failed to add attachment %u to %s\n", (unsigned)i, font->name);
500 memcpy(font->name, name, namelen+1);
501 font->image_font = false;
502 font->has_kerning = !!(((FT_Face)(font->face))->face_flags & FT_FACE_FLAG_KERNING);
506 static qboolean Font_LoadMap(ft2_font_t *font, ft2_font_map_t *mapstart, Uchar _ch, ft2_font_map_t **outmap);
507 static qboolean Font_LoadSize(ft2_font_t *font, float size, qboolean no_texture, qboolean no_kerning)
510 ft2_font_map_t *fmap, temp;
512 if (!(size > 0.001f && size < 1000.0f))
517 if (size < 2) // bogus sizes are not allowed - and they screw up our allocations
522 for (map_index = 0; map_index < MAX_FONT_SIZES; ++map_index)
524 if (!font->font_maps[map_index])
526 // if a similar size has already been loaded, ignore this one
527 //abs(font->font_maps[map_index]->size - size) < 4
528 if (font->font_maps[map_index]->size == size)
532 if (map_index >= MAX_FONT_SIZES)
535 memset(&temp, 0, sizeof(temp));
537 temp.glyphSize = CeilPowerOf2(size*2);
538 temp.sfx = (1.0/64.0)/(double)size;
539 temp.sfy = (1.0/64.0)/(double)size;
540 temp.intSize = -1; // negative value: LoadMap must search now :)
541 if (!Font_LoadMap(font, &temp, 0, &fmap))
543 Con_Printf("ERROR: can't load the first character map for %s\n"
546 Font_UnloadFont(font);
549 font->font_maps[map_index] = temp.next;
551 fmap->sfx = temp.sfx;
552 fmap->sfy = temp.sfy;
556 // load the default kerning vector:
557 if (font->has_kerning)
561 for (l = 0; l < 256; ++l)
563 for (r = 0; r < 256; ++r)
566 ul = qFT_Get_Char_Index(font->face, l);
567 ur = qFT_Get_Char_Index(font->face, r);
568 if (qFT_Get_Kerning(font->face, ul, ur, FT_KERNING_DEFAULT, &kernvec))
570 fmap->kerning.kerning[l][r][0] = 0;
571 fmap->kerning.kerning[l][r][1] = 0;
575 fmap->kerning.kerning[l][r][0] = (kernvec.x >> 6) / fmap->size;
576 fmap->kerning.kerning[l][r][1] = (kernvec.y >> 6) / fmap->size;
586 int Font_IndexForSize(ft2_font_t *font, float _fsize, float *outw, float *outh)
591 int matchsize = -10000;
595 ft2_font_map_t **maps = font->font_maps;
597 fsize = _fsize * vid.height / vid_conheight.value;
605 if (fsize - (float)size >= 0.49)
609 for (m = 0; m < MAX_FONT_SIZES; ++m)
613 // "round up" to the bigger size if two equally-valued matches exist
614 nval = abs(maps[m]->size - size);
615 if (match == -1 || nval < value || (nval == value && matchsize < maps[m]->size))
619 matchsize = maps[m]->size;
620 if (value == 0) // there is no better match
624 if (value <= r_font_size_snapping.value)
628 if (!*outh) *outh = *outw;
629 if (!*outw) *outw = *outh;
632 if (outh) *outh = maps[match]->size * vid_conheight.value / vid.height;
633 if (outw) *outw = maps[match]->size * vid_conwidth.value / vid.width * *outw / _fsize;
638 ft2_font_map_t *Font_MapForIndex(ft2_font_t *font, int index)
640 if (index < 0 || index >= MAX_FONT_SIZES)
642 return font->font_maps[index];
645 static qboolean Font_SetSize(ft2_font_t *font, float w, float h)
647 if (font->currenth == h &&
648 ((!w && (!font->currentw || font->currentw == font->currenth)) || // check if w==h when w is not set
649 font->currentw == w)) // same size has been requested
653 // sorry, but freetype doesn't seem to care about other sizes
656 if (font->image_font)
658 if (qFT_Set_Char_Size((FT_Face)font->next->face, (FT_F26Dot6)(w*64), (FT_F26Dot6)(h*64), 72, 72))
663 if (qFT_Set_Char_Size((FT_Face)font->face, (FT_F26Dot6)(w*64), (FT_F26Dot6)(h*64), 72, 72))
671 qboolean Font_GetKerningForMap(ft2_font_t *font, int map_index, float w, float h, Uchar left, Uchar right, float *outx, float *outy)
673 ft2_font_map_t *fmap;
674 if (!font->has_kerning)
676 if (map_index < 0 || map_index >= MAX_FONT_SIZES)
678 fmap = font->font_maps[map_index];
681 if (left < 256 && right < 256)
683 // quick-kerning, be aware of the size: scale it
684 if (outx) *outx = fmap->kerning.kerning[left][right][0] * w / (float)fmap->size;
685 if (outy) *outy = fmap->kerning.kerning[left][right][1] * h / (float)fmap->size;
693 //if (qFT_Set_Pixel_Sizes((FT_Face)font->face, 0, fmap->size))
694 if (!Font_SetSize(font, w, h))
696 // this deserves an error message
697 Con_Printf("Failed to get kerning for %s\n", font->name);
700 ul = qFT_Get_Char_Index(font->face, left);
701 ur = qFT_Get_Char_Index(font->face, right);
702 if (qFT_Get_Kerning(font->face, ul, ur, FT_KERNING_DEFAULT, &kernvec))
704 if (outx) *outx = kernvec.x * fmap->sfx;
705 if (outy) *outy = kernvec.y * fmap->sfy;
712 qboolean Font_GetKerningForSize(ft2_font_t *font, float w, float h, Uchar left, Uchar right, float *outx, float *outy)
714 return Font_GetKerningForMap(font, Font_IndexForSize(font, h, NULL, NULL), w, h, left, right, outx, outy);
717 static void UnloadMapRec(ft2_font_map_t *map)
721 R_FreeTexture(map->texture);
725 UnloadMapRec(map->next);
729 void Font_UnloadFont(ft2_font_t *font)
732 if (font->attachments && font->attachmentcount)
734 Mem_Free(font->attachments);
735 font->attachmentcount = 0;
736 font->attachments = NULL;
738 for (i = 0; i < MAX_FONT_SIZES; ++i)
740 if (font->font_maps[i])
742 UnloadMapRec(font->font_maps[i]);
743 font->font_maps[i] = NULL;
750 qFT_Done_Face((FT_Face)font->face);
756 static qboolean Font_LoadMap(ft2_font_t *font, ft2_font_map_t *mapstart, Uchar _ch, ft2_font_map_t **outmap)
758 char map_identifier[MAX_QPATH];
759 unsigned long mapidx = _ch / FONT_CHARS_PER_MAP;
767 int gR, gC; // glyph position: row and column
769 ft2_font_map_t *map, *next;
774 int bytesPerPixel = 4; // change the conversion loop too if you change this!
779 if (r_font_use_alpha_textures.integer)
782 if (font->image_font)
783 fontface = (FT_Face)font->next->face;
785 fontface = (FT_Face)font->face;
787 switch(r_font_antialias.integer)
790 switch(r_font_hinting.integer)
793 load_flags = FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT | FT_LOAD_TARGET_MONO | FT_LOAD_MONOCHROME;
797 load_flags = FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_MONO | FT_LOAD_MONOCHROME;
801 load_flags = FT_LOAD_TARGET_MONO | FT_LOAD_MONOCHROME;
807 switch(r_font_hinting.integer)
810 load_flags = FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT | FT_LOAD_TARGET_NORMAL;
813 load_flags = FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT;
816 load_flags = FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_NORMAL;
820 load_flags = FT_LOAD_TARGET_NORMAL;
826 //status = qFT_Set_Pixel_Sizes((FT_Face)font->face, /*size*/0, mapstart->size);
828 if (font->image_font && mapstart->intSize < 0)
829 mapstart->intSize = mapstart->size;
830 if (mapstart->intSize < 0)
832 mapstart->intSize = mapstart->size;
835 if (!Font_SetSize(font, mapstart->intSize, mapstart->intSize))
837 Con_Printf("ERROR: can't set size for font %s: %f ((%f))\n", font->name, mapstart->size, mapstart->intSize);
840 if ((fontface->size->metrics.height>>6) <= mapstart->size)
842 if (mapstart->intSize < 2)
844 Con_Printf("ERROR: no appropriate size found for font %s: %f\n", font->name, mapstart->size);
849 Con_DPrintf("Using size: %f for requested size %f\n", mapstart->intSize, mapstart->size);
852 if (!font->image_font && !Font_SetSize(font, mapstart->intSize, mapstart->intSize))
854 Con_Printf("ERROR: can't set sizes for font %s: %f\n", font->name, mapstart->size);
858 map = Mem_Alloc(font_mempool, sizeof(ft2_font_map_t));
861 Con_Printf("ERROR: Out of memory when loading fontmap for %s\n", font->name);
865 // copy over the information
866 map->size = mapstart->size;
867 map->intSize = mapstart->intSize;
868 map->glyphSize = mapstart->glyphSize;
869 map->sfx = mapstart->sfx;
870 map->sfy = mapstart->sfy;
872 pitch = map->glyphSize * FONT_CHARS_PER_LINE * bytesPerPixel;
873 data = Mem_Alloc(font_mempool, (FONT_CHAR_LINES * map->glyphSize) * pitch);
876 Con_Printf("ERROR: Failed to allocate memory for font %s size %g\n", font->name, map->size);
881 // initialize as white texture with zero alpha
883 while (tp < (FONT_CHAR_LINES * map->glyphSize) * pitch)
885 if (bytesPerPixel == 4)
895 map->start = mapidx * FONT_CHARS_PER_MAP;
897 while(next->next && next->next->start < map->start)
899 map->next = next->next;
904 for (ch = map->start;
905 ch < (FT_ULong)map->start + FONT_CHARS_PER_MAP;
912 unsigned char *imagedata, *dst, *src;
913 glyph_slot_t *mapglyph;
916 mapch = ch - map->start;
918 if (developer_font.integer)
919 Con_DPrint("glyphinfo: ------------- GLYPH INFO -----------------\n");
922 if (gC >= FONT_CHARS_PER_LINE)
924 gC -= FONT_CHARS_PER_LINE;
928 imagedata = data + gR * pitch * map->glyphSize + gC * map->glyphSize * bytesPerPixel;
929 //status = qFT_Load_Char(face, ch, FT_LOAD_RENDER);
930 // we need the glyphIndex
933 if (font->image_font && mapch == ch && img_fontmap[mapch])
935 map->glyphs[mapch].image = true;
938 glyphIndex = qFT_Get_Char_Index(face, ch);
941 // by convention, 0 is the "missing-glyph"-glyph
942 // try to load from a fallback font
943 for(usefont = font->next; usefont != NULL; usefont = usefont->next)
945 if (!Font_SetSize(usefont, mapstart->intSize, mapstart->intSize))
948 face = usefont->face;
949 glyphIndex = qFT_Get_Char_Index(face, ch);
952 status = qFT_Load_Glyph(face, glyphIndex, FT_LOAD_RENDER | load_flags);
959 //Con_Printf("failed to load fallback glyph for char %lx from font %s\n", (unsigned long)ch, font->name);
960 // now we let it use the "missing-glyph"-glyph
970 status = qFT_Load_Glyph(face, glyphIndex, FT_LOAD_RENDER | load_flags);
973 //Con_Printf("failed to load glyph %lu for %s\n", glyphIndex, font->name);
974 Con_DPrintf("failed to load glyph for char %lx from font %s\n", (unsigned long)ch, font->name);
980 bmp = &glyph->bitmap;
985 if (w > map->glyphSize || h > map->glyphSize) {
986 Con_Printf("WARNING: Glyph %lu is too big in font %s, size %g: %i x %i\n", ch, font->name, map->size, w, h);
987 if (w > map->glyphSize)
989 if (h > map->glyphSize)
993 switch (bmp->pixel_mode)
995 case FT_PIXEL_MODE_MONO:
996 if (developer_font.integer)
997 Con_DPrint("glyphinfo: Pixel Mode: MONO\n");
999 case FT_PIXEL_MODE_GRAY2:
1000 if (developer_font.integer)
1001 Con_DPrint("glyphinfo: Pixel Mode: GRAY2\n");
1003 case FT_PIXEL_MODE_GRAY4:
1004 if (developer_font.integer)
1005 Con_DPrint("glyphinfo: Pixel Mode: GRAY4\n");
1007 case FT_PIXEL_MODE_GRAY:
1008 if (developer_font.integer)
1009 Con_DPrint("glyphinfo: Pixel Mode: GRAY\n");
1012 if (developer_font.integer)
1013 Con_DPrintf("glyphinfo: Pixel Mode: Unknown: %i\n", bmp->pixel_mode);
1015 Con_Printf("ERROR: Unrecognized pixel mode for font %s size %f: %i\n", font->name, mapstart->size, bmp->pixel_mode);
1018 for (y = 0; y < h; ++y)
1020 dst = imagedata + y * pitch;
1021 src = bmp->buffer + y * bmp->pitch;
1023 switch (bmp->pixel_mode)
1025 case FT_PIXEL_MODE_MONO:
1026 dst += bytesPerPixel - 1; // shift to alpha byte
1027 for (x = 0; x < bmp->width; x += 8)
1029 unsigned char ch = *src++;
1030 *dst = 255 * !!((ch & 0x80) >> 7); dst += bytesPerPixel;
1031 *dst = 255 * !!((ch & 0x40) >> 6); dst += bytesPerPixel;
1032 *dst = 255 * !!((ch & 0x20) >> 5); dst += bytesPerPixel;
1033 *dst = 255 * !!((ch & 0x10) >> 4); dst += bytesPerPixel;
1034 *dst = 255 * !!((ch & 0x08) >> 3); dst += bytesPerPixel;
1035 *dst = 255 * !!((ch & 0x04) >> 2); dst += bytesPerPixel;
1036 *dst = 255 * !!((ch & 0x02) >> 1); dst += bytesPerPixel;
1037 *dst = 255 * !!((ch & 0x01) >> 0); dst += bytesPerPixel;
1040 case FT_PIXEL_MODE_GRAY2:
1041 dst += bytesPerPixel - 1; // shift to alpha byte
1042 for (x = 0; x < bmp->width; x += 4)
1044 unsigned char ch = *src++;
1045 *dst = ( ((ch & 0xA0) >> 6) * 0x55 ); ch <<= 2; dst += bytesPerPixel;
1046 *dst = ( ((ch & 0xA0) >> 6) * 0x55 ); ch <<= 2; dst += bytesPerPixel;
1047 *dst = ( ((ch & 0xA0) >> 6) * 0x55 ); ch <<= 2; dst += bytesPerPixel;
1048 *dst = ( ((ch & 0xA0) >> 6) * 0x55 ); ch <<= 2; dst += bytesPerPixel;
1051 case FT_PIXEL_MODE_GRAY4:
1052 dst += bytesPerPixel - 1; // shift to alpha byte
1053 for (x = 0; x < bmp->width; x += 2)
1055 unsigned char ch = *src++;
1056 *dst = ( ((ch & 0xF0) >> 4) * 0x11); dst += bytesPerPixel;
1057 *dst = ( ((ch & 0x0F) ) * 0x11); dst += bytesPerPixel;
1060 case FT_PIXEL_MODE_GRAY:
1061 // in this case pitch should equal width
1062 for (tp = 0; tp < bmp->pitch; ++tp)
1063 dst[(bytesPerPixel - 1) + tp*bytesPerPixel] = src[tp]; // copy the grey value into the alpha bytes
1065 //memcpy((void*)dst, (void*)src, bmp->pitch);
1066 //dst += bmp->pitch;
1073 // now fill map->glyphs[ch - map->start]
1074 mapglyph = &map->glyphs[mapch];
1078 // double advance = (double)glyph->metrics.horiAdvance * map->sfx;
1080 double bearingX = (glyph->metrics.horiBearingX >> 6) / map->size;
1081 //double bearingY = (glyph->metrics.horiBearingY >> 6) / map->size;
1082 double advance = (glyph->advance.x >> 6) / map->size;
1083 //double mWidth = (glyph->metrics.width >> 6) / map->size;
1084 //double mHeight = (glyph->metrics.height >> 6) / map->size;
1086 mapglyph->txmin = ( (double)(gC * map->glyphSize) ) / ( (double)(map->glyphSize * FONT_CHARS_PER_LINE) );
1087 mapglyph->txmax = mapglyph->txmin + (double)bmp->width / ( (double)(map->glyphSize * FONT_CHARS_PER_LINE) );
1088 mapglyph->tymin = ( (double)(gR * map->glyphSize) ) / ( (double)(map->glyphSize * FONT_CHAR_LINES) );
1089 mapglyph->tymax = mapglyph->tymin + (double)bmp->rows / ( (double)(map->glyphSize * FONT_CHAR_LINES) );
1090 //mapglyph->vxmin = bearingX;
1091 //mapglyph->vxmax = bearingX + mWidth;
1092 mapglyph->vxmin = glyph->bitmap_left / map->size;
1093 mapglyph->vxmax = mapglyph->vxmin + bmp->width / map->size; // don't ask
1094 //mapglyph->vymin = -bearingY;
1095 //mapglyph->vymax = mHeight - bearingY;
1096 mapglyph->vymin = -glyph->bitmap_top / map->size;
1097 mapglyph->vymax = mapglyph->vymin + bmp->rows / map->size;
1098 //Con_Printf("dpi = %f %f (%f %d) %d %d\n", bmp->width / (mapglyph->vxmax - mapglyph->vxmin), bmp->rows / (mapglyph->vymax - mapglyph->vymin), map->size, map->glyphSize, (int)fontface->size->metrics.x_ppem, (int)fontface->size->metrics.y_ppem);
1099 //mapglyph->advance_x = advance * usefont->size;
1100 mapglyph->advance_x = advance;
1101 mapglyph->advance_y = 0;
1103 if (developer_font.integer)
1105 Con_DPrintf("glyphinfo: Glyph: %lu at (%i, %i)\n", (unsigned long)ch, gC, gR);
1106 Con_DPrintf("glyphinfo: %f, %f, %lu\n", bearingX, map->sfx, (unsigned long)glyph->metrics.horiBearingX);
1107 if (ch >= 32 && ch <= 128)
1108 Con_DPrintf("glyphinfo: Character: %c\n", (int)ch);
1109 Con_DPrintf("glyphinfo: Vertex info:\n");
1110 Con_DPrintf("glyphinfo: X: ( %f -- %f )\n", mapglyph->vxmin, mapglyph->vxmax);
1111 Con_DPrintf("glyphinfo: Y: ( %f -- %f )\n", mapglyph->vymin, mapglyph->vymax);
1112 Con_DPrintf("glyphinfo: Texture info:\n");
1113 Con_DPrintf("glyphinfo: S: ( %f -- %f )\n", mapglyph->txmin, mapglyph->txmax);
1114 Con_DPrintf("glyphinfo: T: ( %f -- %f )\n", mapglyph->tymin, mapglyph->tymax);
1115 Con_DPrintf("glyphinfo: Advance: %f, %f\n", mapglyph->advance_x, mapglyph->advance_y);
1118 map->glyphs[mapch].image = false;
1121 // create a texture from the data now
1123 if (developer_font.integer > 100)
1125 // LordHavoc: why are we writing this? And why not write it as TGA using the appropriate function?
1126 // view using `display -depth 8 -size 512x512 name_page.rgba` (be sure to use a correct -size parameter)
1127 dpsnprintf(map_identifier, sizeof(map_identifier), "%s_%u.rgba", font->name, (unsigned)map->start/FONT_CHARS_PER_MAP);
1128 FS_WriteFile(map_identifier, data, pitch * FONT_CHAR_LINES * map->glyphSize);
1130 dpsnprintf(map_identifier, sizeof(map_identifier), "%s_%u", font->name, (unsigned)map->start/FONT_CHARS_PER_MAP);
1132 // probably use bytesPerPixel here instead?
1133 if (r_font_use_alpha_textures.integer)
1135 map->texture = R_LoadTexture2D(font_texturepool, map_identifier,
1136 map->glyphSize * FONT_CHARS_PER_LINE,
1137 map->glyphSize * FONT_CHAR_LINES,
1138 data, TEXTYPE_ALPHA, TEXF_ALPHA /*gone: | TEXF_ALWAYSPRECACHE*/ /* | TEXF_MIPMAP*/, NULL);
1140 map->texture = R_LoadTexture2D(font_texturepool, map_identifier,
1141 map->glyphSize * FONT_CHARS_PER_LINE,
1142 map->glyphSize * FONT_CHAR_LINES,
1143 data, TEXTYPE_RGBA, TEXF_ALPHA /*gone: | TEXF_ALWAYSPRECACHE*/ /* | TEXF_MIPMAP*/, NULL);
1149 // if the first try isn't successful, keep it with a broken texture
1150 // otherwise we retry to load it every single frame where ft2 rendering is used
1151 // this would be bad...
1152 // only `data' must be freed
1153 Con_Printf("ERROR: Failed to generate texture for font %s size %f map %lu\n",
1154 font->name, mapstart->size, mapidx);
1162 qboolean Font_LoadMapForIndex(ft2_font_t *font, int map_index, Uchar _ch, ft2_font_map_t **outmap)
1164 if (map_index < 0 || map_index >= MAX_FONT_SIZES)
1166 // the first map must have been loaded already
1167 if (!font->font_maps[map_index])
1169 return Font_LoadMap(font, font->font_maps[map_index], _ch, outmap);
1172 ft2_font_map_t *FontMap_FindForChar(ft2_font_map_t *start, Uchar ch)
1174 while (start && start->start + FONT_CHARS_PER_MAP < ch)
1175 start = start->next;
1176 if (start && start->start > ch)