diff --git a/reaction/code/renderer/tr_font.c b/reaction/code/renderer/tr_font.c index 3e5a87e7..43fe6dca 100644 --- a/reaction/code/renderer/tr_font.c +++ b/reaction/code/renderer/tr_font.c @@ -92,55 +92,52 @@ static fontInfo_t registeredFont[MAX_FONTS]; #ifdef BUILD_FREETYPE void R_GetGlyphInfo(FT_GlyphSlot glyph, int *left, int *right, int *width, int *top, int *bottom, int *height, int *pitch) { + *left = _FLOOR( glyph->metrics.horiBearingX ); + *right = _CEIL( glyph->metrics.horiBearingX + glyph->metrics.width ); + *width = _TRUNC(*right - *left); - *left = _FLOOR( glyph->metrics.horiBearingX ); - *right = _CEIL( glyph->metrics.horiBearingX + glyph->metrics.width ); - *width = _TRUNC(*right - *left); - - *top = _CEIL( glyph->metrics.horiBearingY ); - *bottom = _FLOOR( glyph->metrics.horiBearingY - glyph->metrics.height ); - *height = _TRUNC( *top - *bottom ); - *pitch = ( qtrue ? (*width+3) & -4 : (*width+7) >> 3 ); + *top = _CEIL( glyph->metrics.horiBearingY ); + *bottom = _FLOOR( glyph->metrics.horiBearingY - glyph->metrics.height ); + *height = _TRUNC( *top - *bottom ); + *pitch = ( qtrue ? (*width+3) & -4 : (*width+7) >> 3 ); } FT_Bitmap *R_RenderGlyph(FT_GlyphSlot glyph, glyphInfo_t* glyphOut) { + FT_Bitmap *bit2; + int left, right, width, top, bottom, height, pitch, size; - FT_Bitmap *bit2; - int left, right, width, top, bottom, height, pitch, size; + R_GetGlyphInfo(glyph, &left, &right, &width, &top, &bottom, &height, &pitch); - R_GetGlyphInfo(glyph, &left, &right, &width, &top, &bottom, &height, &pitch); + if ( glyph->format == ft_glyph_format_outline ) { + size = pitch*height; - if ( glyph->format == ft_glyph_format_outline ) { - size = pitch*height; + bit2 = ri.Malloc(sizeof(FT_Bitmap)); - bit2 = ri.Malloc(sizeof(FT_Bitmap)); + bit2->width = width; + bit2->rows = height; + bit2->pitch = pitch; + bit2->pixel_mode = ft_pixel_mode_grays; + //bit2->pixel_mode = ft_pixel_mode_mono; + bit2->buffer = ri.Malloc(pitch*height); + bit2->num_grays = 256; - bit2->width = width; - bit2->rows = height; - bit2->pitch = pitch; - bit2->pixel_mode = ft_pixel_mode_grays; - //bit2->pixel_mode = ft_pixel_mode_mono; - bit2->buffer = ri.Malloc(pitch*height); - bit2->num_grays = 256; + Com_Memset( bit2->buffer, 0, size ); - Com_Memset( bit2->buffer, 0, size ); + FT_Outline_Translate( &glyph->outline, -left, -bottom ); - FT_Outline_Translate( &glyph->outline, -left, -bottom ); + FT_Outline_Get_Bitmap( ftLibrary, &glyph->outline, bit2 ); - FT_Outline_Get_Bitmap( ftLibrary, &glyph->outline, bit2 ); + glyphOut->height = height; + glyphOut->pitch = pitch; + glyphOut->top = (glyph->metrics.horiBearingY >> 6) + 1; + glyphOut->bottom = bottom; - glyphOut->height = height; - glyphOut->pitch = pitch; - glyphOut->top = (glyph->metrics.horiBearingY >> 6) + 1; - glyphOut->bottom = bottom; - - return bit2; - } - else { - ri.Printf(PRINT_ALL, "Non-outline fonts are not supported\n"); - } - return NULL; + return bit2; + } else { + ri.Printf(PRINT_ALL, "Non-outline fonts are not supported\n"); + } + return NULL; } void WriteTGA (char *filename, byte *data, int width, int height) { @@ -192,62 +189,62 @@ void WriteTGA (char *filename, byte *data, int width, int height) { } static glyphInfo_t *RE_ConstructGlyphInfo(unsigned char *imageOut, int *xOut, int *yOut, int *maxHeight, FT_Face face, const unsigned char c, qboolean calcHeight) { - int i; - static glyphInfo_t glyph; - unsigned char *src, *dst; - float scaled_width, scaled_height; - FT_Bitmap *bitmap = NULL; + int i; + static glyphInfo_t glyph; + unsigned char *src, *dst; + float scaled_width, scaled_height; + FT_Bitmap *bitmap = NULL; - Com_Memset(&glyph, 0, sizeof(glyphInfo_t)); - // make sure everything is here - if (face != NULL) { - FT_Load_Glyph(face, FT_Get_Char_Index( face, c), FT_LOAD_DEFAULT ); - bitmap = R_RenderGlyph(face->glyph, &glyph); - if (bitmap) { - glyph.xSkip = (face->glyph->metrics.horiAdvance >> 6) + 1; - } else { - return &glyph; - } + Com_Memset(&glyph, 0, sizeof(glyphInfo_t)); + // make sure everything is here + if (face != NULL) { + FT_Load_Glyph(face, FT_Get_Char_Index( face, c), FT_LOAD_DEFAULT ); + bitmap = R_RenderGlyph(face->glyph, &glyph); + if (bitmap) { + glyph.xSkip = (face->glyph->metrics.horiAdvance >> 6) + 1; + } else { + return &glyph; + } - if (glyph.height > *maxHeight) { - *maxHeight = glyph.height; - } + if (glyph.height > *maxHeight) { + *maxHeight = glyph.height; + } - if (calcHeight) { - ri.Free(bitmap->buffer); - ri.Free(bitmap); - return &glyph; - } + if (calcHeight) { + ri.Free(bitmap->buffer); + ri.Free(bitmap); + return &glyph; + } /* - // need to convert to power of 2 sizes so we do not get - // any scaling from the gl upload - for (scaled_width = 1 ; scaled_width < glyph.pitch ; scaled_width<<=1) - ; - for (scaled_height = 1 ; scaled_height < glyph.height ; scaled_height<<=1) - ; + // need to convert to power of 2 sizes so we do not get + // any scaling from the gl upload + for (scaled_width = 1 ; scaled_width < glyph.pitch ; scaled_width<<=1) + ; + for (scaled_height = 1 ; scaled_height < glyph.height ; scaled_height<<=1) + ; */ - scaled_width = glyph.pitch; - scaled_height = glyph.height; + scaled_width = glyph.pitch; + scaled_height = glyph.height; - // we need to make sure we fit - if (*xOut + scaled_width + 1 >= 255) { - *xOut = 0; - *yOut += *maxHeight + 1; - } + // we need to make sure we fit + if (*xOut + scaled_width + 1 >= 255) { + *xOut = 0; + *yOut += *maxHeight + 1; + } - if (*yOut + *maxHeight + 1 >= 255) { - *yOut = -1; - *xOut = -1; - ri.Free(bitmap->buffer); - ri.Free(bitmap); - return &glyph; - } + if (*yOut + *maxHeight + 1 >= 255) { + *yOut = -1; + *xOut = -1; + ri.Free(bitmap->buffer); + ri.Free(bitmap); + return &glyph; + } - src = bitmap->buffer; - dst = imageOut + (*yOut * 256) + *xOut; + src = bitmap->buffer; + dst = imageOut + (*yOut * 256) + *xOut; if (bitmap->pixel_mode == ft_pixel_mode_mono) { for (i = 0; i < glyph.height; i++) { @@ -264,7 +261,7 @@ static glyphInfo_t *RE_ConstructGlyphInfo(unsigned char *imageOut, int *xOut, in *_dst = 0xff; } mask >>= 1; - + if ( mask == 0 ) { mask = 0x80; } @@ -273,33 +270,32 @@ static glyphInfo_t *RE_ConstructGlyphInfo(unsigned char *imageOut, int *xOut, in src += glyph.pitch; dst += 256; - } } else { - for (i = 0; i < glyph.height; i++) { - Com_Memcpy(dst, src, glyph.pitch); - src += glyph.pitch; + for (i = 0; i < glyph.height; i++) { + Com_Memcpy(dst, src, glyph.pitch); + src += glyph.pitch; dst += 256; - } + } } - // we now have an 8 bit per pixel grey scale bitmap - // that is width wide and pf->ftSize->metrics.y_ppem tall + // we now have an 8 bit per pixel grey scale bitmap + // that is width wide and pf->ftSize->metrics.y_ppem tall - glyph.imageHeight = scaled_height; - glyph.imageWidth = scaled_width; - glyph.s = (float)*xOut / 256; - glyph.t = (float)*yOut / 256; - glyph.s2 = glyph.s + (float)scaled_width / 256; - glyph.t2 = glyph.t + (float)scaled_height / 256; + glyph.imageHeight = scaled_height; + glyph.imageWidth = scaled_width; + glyph.s = (float)*xOut / 256; + glyph.t = (float)*yOut / 256; + glyph.s2 = glyph.s + (float)scaled_width / 256; + glyph.t2 = glyph.t + (float)scaled_height / 256; - *xOut += scaled_width + 1; - } + *xOut += scaled_width + 1; + } - ri.Free(bitmap->buffer); - ri.Free(bitmap); + ri.Free(bitmap->buffer); + ri.Free(bitmap); - return &glyph; + return &glyph; } #endif @@ -336,26 +332,26 @@ float readFloat( void ) { void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font) { #ifdef BUILD_FREETYPE - FT_Face face; - int j, k, xOut, yOut, lastStart, imageNumber; - int scaledSize, newSize, maxHeight, left; - unsigned char *out, *imageBuff; - glyphInfo_t *glyph; - image_t *image; - qhandle_t h; + FT_Face face; + int j, k, xOut, yOut, lastStart, imageNumber; + int scaledSize, newSize, maxHeight, left; + unsigned char *out, *imageBuff; + glyphInfo_t *glyph; + image_t *image; + qhandle_t h; float max; #endif - void *faceData; + void *faceData; int i, len; - char name[1024]; + char name[1024]; float dpi = 72; // float glyphScale = 72.0f / dpi; // change the scale to be relative to 1 based on 72 dpi ( so dpi of 144 means a scale of .5 ) - if (!fontName) { - ri.Printf(PRINT_ALL, "RE_RegisterFont: called with empty name\n"); - return; - } + if (!fontName) { + ri.Printf(PRINT_ALL, "RE_RegisterFont: called with empty name\n"); + return; + } if (pointSize <= 0) { pointSize = 12; @@ -366,10 +362,10 @@ void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font) { // make sure the render thread is stopped R_SyncRenderThread(); - if (registeredFontCount >= MAX_FONTS) { - ri.Printf(PRINT_ALL, "RE_RegisterFont: Too many fonts registered already.\n"); - return; - } + if (registeredFontCount >= MAX_FONTS) { + ri.Printf(PRINT_ALL, "RE_RegisterFont: Too many fonts registered already.\n"); + return; + } Com_sprintf(name, sizeof(name), "fonts/fontImage_%i.dat",pointSize); for (i = 0; i < registeredFontCount; i++) { @@ -408,127 +404,127 @@ void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font) { for (i = GLYPH_START; i < GLYPH_END; i++) { font->glyphs[i].glyph = RE_RegisterShaderNoMip(font->glyphs[i].shaderName); } - Com_Memcpy(®isteredFont[registeredFontCount++], font, sizeof(fontInfo_t)); + Com_Memcpy(®isteredFont[registeredFontCount++], font, sizeof(fontInfo_t)); return; } #ifndef BUILD_FREETYPE - ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType code not available\n"); + ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType code not available\n"); #else - if (ftLibrary == NULL) { - ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType not initialized.\n"); - return; - } + if (ftLibrary == NULL) { + ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType not initialized.\n"); + return; + } - len = ri.FS_ReadFile(fontName, &faceData); - if (len <= 0) { - ri.Printf(PRINT_ALL, "RE_RegisterFont: Unable to read font file\n"); - return; - } + len = ri.FS_ReadFile(fontName, &faceData); + if (len <= 0) { + ri.Printf(PRINT_ALL, "RE_RegisterFont: Unable to read font file\n"); + return; + } - // allocate on the stack first in case we fail - if (FT_New_Memory_Face( ftLibrary, faceData, len, 0, &face )) { - ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType2, unable to allocate new face.\n"); - return; - } + // allocate on the stack first in case we fail + if (FT_New_Memory_Face( ftLibrary, faceData, len, 0, &face )) { + ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType2, unable to allocate new face.\n"); + return; + } - if (FT_Set_Char_Size( face, pointSize << 6, pointSize << 6, dpi, dpi)) { - ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType2, Unable to set face char size.\n"); - return; - } + if (FT_Set_Char_Size( face, pointSize << 6, pointSize << 6, dpi, dpi)) { + ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType2, Unable to set face char size.\n"); + return; + } - //*font = ®isteredFonts[registeredFontCount++]; + //*font = ®isteredFonts[registeredFontCount++]; - // make a 256x256 image buffer, once it is full, register it, clean it and keep going - // until all glyphs are rendered + // make a 256x256 image buffer, once it is full, register it, clean it and keep going + // until all glyphs are rendered - out = ri.Malloc(1024*1024); - if (out == NULL) { - ri.Printf(PRINT_ALL, "RE_RegisterFont: ri.Malloc failure during output image creation.\n"); - return; - } - Com_Memset(out, 0, 1024*1024); + out = ri.Malloc(1024*1024); + if (out == NULL) { + ri.Printf(PRINT_ALL, "RE_RegisterFont: ri.Malloc failure during output image creation.\n"); + return; + } + Com_Memset(out, 0, 1024*1024); - maxHeight = 0; + maxHeight = 0; - for (i = GLYPH_START; i < GLYPH_END; i++) { - glyph = RE_ConstructGlyphInfo(out, &xOut, &yOut, &maxHeight, face, (unsigned char)i, qtrue); - } + for (i = GLYPH_START; i < GLYPH_END; i++) { + glyph = RE_ConstructGlyphInfo(out, &xOut, &yOut, &maxHeight, face, (unsigned char)i, qtrue); + } - xOut = 0; - yOut = 0; - i = GLYPH_START; - lastStart = i; - imageNumber = 0; + xOut = 0; + yOut = 0; + i = GLYPH_START; + lastStart = i; + imageNumber = 0; - while ( i <= GLYPH_END ) { + while ( i <= GLYPH_END ) { - glyph = RE_ConstructGlyphInfo(out, &xOut, &yOut, &maxHeight, face, (unsigned char)i, qfalse); + glyph = RE_ConstructGlyphInfo(out, &xOut, &yOut, &maxHeight, face, (unsigned char)i, qfalse); - if (xOut == -1 || yOut == -1 || i == GLYPH_END) { - // ran out of room - // we need to create an image from the bitmap, set all the handles in the glyphs to this point - // + if (xOut == -1 || yOut == -1 || i == GLYPH_END) { + // ran out of room + // we need to create an image from the bitmap, set all the handles in the glyphs to this point + // - scaledSize = 256*256; - newSize = scaledSize * 4; - imageBuff = ri.Malloc(newSize); - left = 0; - max = 0; - for ( k = 0; k < (scaledSize) ; k++ ) { - if (max < out[k]) { - max = out[k]; - } - } + scaledSize = 256*256; + newSize = scaledSize * 4; + imageBuff = ri.Malloc(newSize); + left = 0; + max = 0; + for ( k = 0; k < (scaledSize) ; k++ ) { + if (max < out[k]) { + max = out[k]; + } + } if (max > 0) { max = 255/max; } - for ( k = 0; k < (scaledSize) ; k++ ) { - imageBuff[left++] = 255; - imageBuff[left++] = 255; - imageBuff[left++] = 255; + for ( k = 0; k < (scaledSize) ; k++ ) { + imageBuff[left++] = 255; + imageBuff[left++] = 255; + imageBuff[left++] = 255; - imageBuff[left++] = ((float)out[k] * max); - } + imageBuff[left++] = ((float)out[k] * max); + } Com_sprintf (name, sizeof(name), "fonts/fontImage_%i_%i.tga", imageNumber++, pointSize); if (r_saveFontData->integer) { - WriteTGA(name, imageBuff, 256, 256); + WriteTGA(name, imageBuff, 256, 256); } - //Com_sprintf (name, sizeof(name), "fonts/fontImage_%i_%i", imageNumber++, pointSize); - image = R_CreateImage(name, imageBuff, 256, 256, qfalse, qfalse, GL_CLAMP_TO_EDGE); - h = RE_RegisterShaderFromImage(name, LIGHTMAP_2D, image, qfalse); - for (j = lastStart; j < i; j++) { - font->glyphs[j].glyph = h; + //Com_sprintf (name, sizeof(name), "fonts/fontImage_%i_%i", imageNumber++, pointSize); + image = R_CreateImage(name, imageBuff, 256, 256, qfalse, qfalse, GL_CLAMP_TO_EDGE); + h = RE_RegisterShaderFromImage(name, LIGHTMAP_2D, image, qfalse); + for (j = lastStart; j < i; j++) { + font->glyphs[j].glyph = h; Q_strncpyz(font->glyphs[j].shaderName, name, sizeof(font->glyphs[j].shaderName)); - } - lastStart = i; - Com_Memset(out, 0, 1024*1024); - xOut = 0; - yOut = 0; - ri.Free(imageBuff); + } + lastStart = i; + Com_Memset(out, 0, 1024*1024); + xOut = 0; + yOut = 0; + ri.Free(imageBuff); i++; - } else { - Com_Memcpy(&font->glyphs[i], glyph, sizeof(glyphInfo_t)); - i++; - } - } + } else { + Com_Memcpy(&font->glyphs[i], glyph, sizeof(glyphInfo_t)); + i++; + } + } registeredFont[registeredFontCount].glyphScale = glyphScale; font->glyphScale = glyphScale; - Com_Memcpy(®isteredFont[registeredFontCount++], font, sizeof(fontInfo_t)); + Com_Memcpy(®isteredFont[registeredFontCount++], font, sizeof(fontInfo_t)); - if (r_saveFontData->integer) { + if (r_saveFontData->integer) { ri.FS_WriteFile(va("fonts/fontImage_%i.dat", pointSize), font, sizeof(fontInfo_t)); } - ri.Free(out); - - ri.FS_FreeFile(faceData); + ri.Free(out); + + ri.FS_FreeFile(faceData); #endif } @@ -536,20 +532,20 @@ void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font) { void R_InitFreeType(void) { #ifdef BUILD_FREETYPE - if (FT_Init_FreeType( &ftLibrary )) { - ri.Printf(PRINT_ALL, "R_InitFreeType: Unable to initialize FreeType.\n"); - } + if (FT_Init_FreeType( &ftLibrary )) { + ri.Printf(PRINT_ALL, "R_InitFreeType: Unable to initialize FreeType.\n"); + } #endif - registeredFontCount = 0; + registeredFontCount = 0; } void R_DoneFreeType(void) { #ifdef BUILD_FREETYPE - if (ftLibrary) { - FT_Done_FreeType( ftLibrary ); - ftLibrary = NULL; - } + if (ftLibrary) { + FT_Done_FreeType( ftLibrary ); + ftLibrary = NULL; + } #endif registeredFontCount = 0; }