00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #include "tr_local.h"
00074 #include "../qcommon/qcommon.h"
00075
00076 #ifdef BUILD_FREETYPE
00077 #include "../ft2/fterrors.h"
00078 #include "../ft2/ftsystem.h"
00079 #include "../ft2/ftimage.h"
00080 #include "../ft2/freetype.h"
00081 #include "../ft2/ftoutln.h"
00082
00083 #define _FLOOR(x) ((x) & -64)
00084 #define _CEIL(x) (((x)+63) & -64)
00085 #define _TRUNC(x) ((x) >> 6)
00086
00087 FT_Library ftLibrary = NULL;
00088 #endif
00089
00090 #define MAX_FONTS 6
00091 static int registeredFontCount = 0;
00092 static fontInfo_t registeredFont[MAX_FONTS];
00093
00094 #ifdef BUILD_FREETYPE
00095 void R_GetGlyphInfo(FT_GlyphSlot glyph, int *left, int *right, int *width, int *top, int *bottom, int *height, int *pitch) {
00096
00097 *left = _FLOOR( glyph->metrics.horiBearingX );
00098 *right = _CEIL( glyph->metrics.horiBearingX + glyph->metrics.width );
00099 *width = _TRUNC(*right - *left);
00100
00101 *top = _CEIL( glyph->metrics.horiBearingY );
00102 *bottom = _FLOOR( glyph->metrics.horiBearingY - glyph->metrics.height );
00103 *height = _TRUNC( *top - *bottom );
00104 *pitch = ( qtrue ? (*width+3) & -4 : (*width+7) >> 3 );
00105 }
00106
00107
00108 FT_Bitmap *R_RenderGlyph(FT_GlyphSlot glyph, glyphInfo_t* glyphOut) {
00109
00110 FT_Bitmap *bit2;
00111 int left, right, width, top, bottom, height, pitch, size;
00112
00113 R_GetGlyphInfo(glyph, &left, &right, &width, &top, &bottom, &height, &pitch);
00114
00115 if ( glyph->format == ft_glyph_format_outline ) {
00116 size = pitch*height;
00117
00118 bit2 = Z_Malloc(sizeof(FT_Bitmap));
00119
00120 bit2->width = width;
00121 bit2->rows = height;
00122 bit2->pitch = pitch;
00123 bit2->pixel_mode = ft_pixel_mode_grays;
00124
00125 bit2->buffer = Z_Malloc(pitch*height);
00126 bit2->num_grays = 256;
00127
00128 Com_Memset( bit2->buffer, 0, size );
00129
00130 FT_Outline_Translate( &glyph->outline, -left, -bottom );
00131
00132 FT_Outline_Get_Bitmap( ftLibrary, &glyph->outline, bit2 );
00133
00134 glyphOut->height = height;
00135 glyphOut->pitch = pitch;
00136 glyphOut->top = (glyph->metrics.horiBearingY >> 6) + 1;
00137 glyphOut->bottom = bottom;
00138
00139 return bit2;
00140 }
00141 else {
00142 ri.Printf(PRINT_ALL, "Non-outline fonts are not supported\n");
00143 }
00144 return NULL;
00145 }
00146
00147 void WriteTGA (char *filename, byte *data, int width, int height) {
00148 byte *buffer;
00149 int i, c;
00150
00151 buffer = Z_Malloc(width*height*4 + 18);
00152 Com_Memset (buffer, 0, 18);
00153 buffer[2] = 2;
00154 buffer[12] = width&255;
00155 buffer[13] = width>>8;
00156 buffer[14] = height&255;
00157 buffer[15] = height>>8;
00158 buffer[16] = 32;
00159
00160
00161 c = 18 + width * height * 4;
00162 for (i=18 ; i<c ; i+=4)
00163 {
00164 buffer[i] = data[i-18+2];
00165 buffer[i+1] = data[i-18+1];
00166 buffer[i+2] = data[i-18+0];
00167 buffer[i+3] = data[i-18+3];
00168 }
00169
00170 ri.FS_WriteFile(filename, buffer, c);
00171
00172
00173
00174
00175
00176 Z_Free (buffer);
00177 }
00178
00179 static glyphInfo_t *RE_ConstructGlyphInfo(unsigned char *imageOut, int *xOut, int *yOut, int *maxHeight, FT_Face face, const unsigned char c, qboolean calcHeight) {
00180 int i;
00181 static glyphInfo_t glyph;
00182 unsigned char *src, *dst;
00183 float scaled_width, scaled_height;
00184 FT_Bitmap *bitmap = NULL;
00185
00186 Com_Memset(&glyph, 0, sizeof(glyphInfo_t));
00187
00188 if (face != NULL) {
00189 FT_Load_Glyph(face, FT_Get_Char_Index( face, c), FT_LOAD_DEFAULT );
00190 bitmap = R_RenderGlyph(face->glyph, &glyph);
00191 if (bitmap) {
00192 glyph.xSkip = (face->glyph->metrics.horiAdvance >> 6) + 1;
00193 } else {
00194 return &glyph;
00195 }
00196
00197 if (glyph.height > *maxHeight) {
00198 *maxHeight = glyph.height;
00199 }
00200
00201 if (calcHeight) {
00202 Z_Free(bitmap->buffer);
00203 Z_Free(bitmap);
00204 return &glyph;
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 scaled_width = glyph.pitch;
00217 scaled_height = glyph.height;
00218
00219
00220 if (*xOut + scaled_width + 1 >= 255) {
00221 if (*yOut + *maxHeight + 1 >= 255) {
00222 *yOut = -1;
00223 *xOut = -1;
00224 Z_Free(bitmap->buffer);
00225 Z_Free(bitmap);
00226 return &glyph;
00227 } else {
00228 *xOut = 0;
00229 *yOut += *maxHeight + 1;
00230 }
00231 } else if (*yOut + *maxHeight + 1 >= 255) {
00232 *yOut = -1;
00233 *xOut = -1;
00234 Z_Free(bitmap->buffer);
00235 Z_Free(bitmap);
00236 return &glyph;
00237 }
00238
00239
00240 src = bitmap->buffer;
00241 dst = imageOut + (*yOut * 256) + *xOut;
00242
00243 if (bitmap->pixel_mode == ft_pixel_mode_mono) {
00244 for (i = 0; i < glyph.height; i++) {
00245 int j;
00246 unsigned char *_src = src;
00247 unsigned char *_dst = dst;
00248 unsigned char mask = 0x80;
00249 unsigned char val = *_src;
00250 for (j = 0; j < glyph.pitch; j++) {
00251 if (mask == 0x80) {
00252 val = *_src++;
00253 }
00254 if (val & mask) {
00255 *_dst = 0xff;
00256 }
00257 mask >>= 1;
00258
00259 if ( mask == 0 ) {
00260 mask = 0x80;
00261 }
00262 _dst++;
00263 }
00264
00265 src += glyph.pitch;
00266 dst += 256;
00267
00268 }
00269 } else {
00270 for (i = 0; i < glyph.height; i++) {
00271 Com_Memcpy(dst, src, glyph.pitch);
00272 src += glyph.pitch;
00273 dst += 256;
00274 }
00275 }
00276
00277
00278
00279
00280 glyph.imageHeight = scaled_height;
00281 glyph.imageWidth = scaled_width;
00282 glyph.s = (float)*xOut / 256;
00283 glyph.t = (float)*yOut / 256;
00284 glyph.s2 = glyph.s + (float)scaled_width / 256;
00285 glyph.t2 = glyph.t + (float)scaled_height / 256;
00286
00287 *xOut += scaled_width + 1;
00288 }
00289
00290 Z_Free(bitmap->buffer);
00291 Z_Free(bitmap);
00292
00293 return &glyph;
00294 }
00295 #endif
00296
00297 static int fdOffset;
00298 static byte *fdFile;
00299
00300 int readInt() {
00301 int i = fdFile[fdOffset]+(fdFile[fdOffset+1]<<8)+(fdFile[fdOffset+2]<<16)+(fdFile[fdOffset+3]<<24);
00302 fdOffset += 4;
00303 return i;
00304 }
00305
00306 typedef union {
00307 byte fred[4];
00308 float ffred;
00309 } poor;
00310
00311 float readFloat() {
00312 poor me;
00313 #if idppc
00314 me.fred[0] = fdFile[fdOffset+3];
00315 me.fred[1] = fdFile[fdOffset+2];
00316 me.fred[2] = fdFile[fdOffset+1];
00317 me.fred[3] = fdFile[fdOffset+0];
00318 #else
00319 me.fred[0] = fdFile[fdOffset+0];
00320 me.fred[1] = fdFile[fdOffset+1];
00321 me.fred[2] = fdFile[fdOffset+2];
00322 me.fred[3] = fdFile[fdOffset+3];
00323 #endif
00324 fdOffset += 4;
00325 return me.ffred;
00326 }
00327
00328 void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font) {
00329 #ifdef BUILD_FREETYPE
00330 FT_Face face;
00331 int j, k, xOut, yOut, lastStart, imageNumber;
00332 int scaledSize, newSize, maxHeight, left, satLevels;
00333 unsigned char *out, *imageBuff;
00334 glyphInfo_t *glyph;
00335 image_t *image;
00336 qhandle_t h;
00337 float max;
00338 #endif
00339 void *faceData;
00340 int i, len;
00341 char name[1024];
00342 float dpi = 72;
00343 float glyphScale = 72.0f / dpi;
00344
00345 if (pointSize <= 0) {
00346 pointSize = 12;
00347 }
00348
00349 glyphScale *= 48.0f / pointSize;
00350
00351
00352 R_SyncRenderThread();
00353
00354 if (registeredFontCount >= MAX_FONTS) {
00355 ri.Printf(PRINT_ALL, "RE_RegisterFont: Too many fonts registered already.\n");
00356 return;
00357 }
00358
00359 Com_sprintf(name, sizeof(name), "fonts/fontImage_%i.dat",pointSize);
00360 for (i = 0; i < registeredFontCount; i++) {
00361 if (Q_stricmp(name, registeredFont[i].name) == 0) {
00362 Com_Memcpy(font, ®isteredFont[i], sizeof(fontInfo_t));
00363 return;
00364 }
00365 }
00366
00367 len = ri.FS_ReadFile(name, NULL);
00368 if (len == sizeof(fontInfo_t)) {
00369 ri.FS_ReadFile(name, &faceData);
00370 fdOffset = 0;
00371 fdFile = faceData;
00372 for(i=0; i<GLYPHS_PER_FONT; i++) {
00373 font->glyphs[i].height = readInt();
00374 font->glyphs[i].top = readInt();
00375 font->glyphs[i].bottom = readInt();
00376 font->glyphs[i].pitch = readInt();
00377 font->glyphs[i].xSkip = readInt();
00378 font->glyphs[i].imageWidth = readInt();
00379 font->glyphs[i].imageHeight = readInt();
00380 font->glyphs[i].s = readFloat();
00381 font->glyphs[i].t = readFloat();
00382 font->glyphs[i].s2 = readFloat();
00383 font->glyphs[i].t2 = readFloat();
00384 font->glyphs[i].glyph = readInt();
00385 Com_Memcpy(font->glyphs[i].shaderName, &fdFile[fdOffset], 32);
00386 fdOffset += 32;
00387 }
00388 font->glyphScale = readFloat();
00389 Com_Memcpy(font->name, &fdFile[fdOffset], MAX_QPATH);
00390
00391
00392 Q_strncpyz(font->name, name, sizeof(font->name));
00393 for (i = GLYPH_START; i < GLYPH_END; i++) {
00394 font->glyphs[i].glyph = RE_RegisterShaderNoMip(font->glyphs[i].shaderName);
00395 }
00396 Com_Memcpy(®isteredFont[registeredFontCount++], font, sizeof(fontInfo_t));
00397 return;
00398 }
00399
00400 #ifndef BUILD_FREETYPE
00401 ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType code not available\n");
00402 #else
00403 if (ftLibrary == NULL) {
00404 ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType not initialized.\n");
00405 return;
00406 }
00407
00408 len = ri.FS_ReadFile(fontName, &faceData);
00409 if (len <= 0) {
00410 ri.Printf(PRINT_ALL, "RE_RegisterFont: Unable to read font file\n");
00411 return;
00412 }
00413
00414
00415 if (FT_New_Memory_Face( ftLibrary, faceData, len, 0, &face )) {
00416 ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType2, unable to allocate new face.\n");
00417 return;
00418 }
00419
00420
00421 if (FT_Set_Char_Size( face, pointSize << 6, pointSize << 6, dpi, dpi)) {
00422 ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType2, Unable to set face char size.\n");
00423 return;
00424 }
00425
00426
00427
00428
00429
00430
00431 out = Z_Malloc(1024*1024);
00432 if (out == NULL) {
00433 ri.Printf(PRINT_ALL, "RE_RegisterFont: Z_Malloc failure during output image creation.\n");
00434 return;
00435 }
00436 Com_Memset(out, 0, 1024*1024);
00437
00438 maxHeight = 0;
00439
00440 for (i = GLYPH_START; i < GLYPH_END; i++) {
00441 glyph = RE_ConstructGlyphInfo(out, &xOut, &yOut, &maxHeight, face, (unsigned char)i, qtrue);
00442 }
00443
00444 xOut = 0;
00445 yOut = 0;
00446 i = GLYPH_START;
00447 lastStart = i;
00448 imageNumber = 0;
00449
00450 while ( i <= GLYPH_END ) {
00451
00452 glyph = RE_ConstructGlyphInfo(out, &xOut, &yOut, &maxHeight, face, (unsigned char)i, qfalse);
00453
00454 if (xOut == -1 || yOut == -1 || i == GLYPH_END) {
00455
00456
00457
00458
00459 scaledSize = 256*256;
00460 newSize = scaledSize * 4;
00461 imageBuff = Z_Malloc(newSize);
00462 left = 0;
00463 max = 0;
00464 satLevels = 255;
00465 for ( k = 0; k < (scaledSize) ; k++ ) {
00466 if (max < out[k]) {
00467 max = out[k];
00468 }
00469 }
00470
00471 if (max > 0) {
00472 max = 255/max;
00473 }
00474
00475 for ( k = 0; k < (scaledSize) ; k++ ) {
00476 imageBuff[left++] = 255;
00477 imageBuff[left++] = 255;
00478 imageBuff[left++] = 255;
00479
00480 imageBuff[left++] = ((float)out[k] * max);
00481 }
00482
00483 Com_sprintf (name, sizeof(name), "fonts/fontImage_%i_%i.tga", imageNumber++, pointSize);
00484 if (r_saveFontData->integer) {
00485 WriteTGA(name, imageBuff, 256, 256);
00486 }
00487
00488
00489 image = R_CreateImage(name, imageBuff, 256, 256, qfalse, qfalse, GL_CLAMP);
00490 h = RE_RegisterShaderFromImage(name, LIGHTMAP_2D, image, qfalse);
00491 for (j = lastStart; j < i; j++) {
00492 font->glyphs[j].glyph = h;
00493 Q_strncpyz(font->glyphs[j].shaderName, name, sizeof(font->glyphs[j].shaderName));
00494 }
00495 lastStart = i;
00496 Com_Memset(out, 0, 1024*1024);
00497 xOut = 0;
00498 yOut = 0;
00499 Z_Free(imageBuff);
00500 i++;
00501 } else {
00502 Com_Memcpy(&font->glyphs[i], glyph, sizeof(glyphInfo_t));
00503 i++;
00504 }
00505 }
00506
00507 registeredFont[registeredFontCount].glyphScale = glyphScale;
00508 font->glyphScale = glyphScale;
00509 Com_Memcpy(®isteredFont[registeredFontCount++], font, sizeof(fontInfo_t));
00510
00511 if (r_saveFontData->integer) {
00512 ri.FS_WriteFile(va("fonts/fontImage_%i.dat", pointSize), font, sizeof(fontInfo_t));
00513 }
00514
00515 Z_Free(out);
00516
00517 ri.FS_FreeFile(faceData);
00518 #endif
00519 }
00520
00521
00522
00523 void R_InitFreeType() {
00524 #ifdef BUILD_FREETYPE
00525 if (FT_Init_FreeType( &ftLibrary )) {
00526 ri.Printf(PRINT_ALL, "R_InitFreeType: Unable to initialize FreeType.\n");
00527 }
00528 #endif
00529 registeredFontCount = 0;
00530 }
00531
00532
00533 void R_DoneFreeType() {
00534 #ifdef BUILD_FREETYPE
00535 if (ftLibrary) {
00536 FT_Done_FreeType( ftLibrary );
00537 ftLibrary = NULL;
00538 }
00539 #endif
00540 registeredFontCount = 0;
00541 }
00542