fix performance problems with using multiple font sizes

This commit is contained in:
dborth 2009-07-08 07:14:38 +00:00
parent c934f9321d
commit 3dd7f60c54
6 changed files with 86 additions and 110 deletions

View File

@ -22,25 +22,35 @@
#include "FreeTypeGX.h"
/**
* Default constructor for the FreeTypeGX class.
*
* @param textureFormat Optional format (GX_TF_*) of the texture as defined by the libogc gx.h header file. If not specified default value is GX_TF_RGBA8.
* @param vertexIndex Optional vertex format index (GX_VTXFMT*) of the glyph textures as defined by the libogc gx.h header file. If not specified default value is GX_VTXFMT1.
*/
FreeTypeGX::FreeTypeGX(uint8_t textureFormat, uint8_t vertexIndex) {
FT_Init_FreeType(&this->ftLibrary);
static FT_Library ftLibrary; /**< FreeType FT_Library instance. */
static FT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */
static FT_GlyphSlot ftSlot; /**< FreeType reusable FT_GlyphSlot glyph container object. */
this->textureFormat = textureFormat;
this->setVertexFormat(vertexIndex);
this->setCompatibilityMode(FTGX_COMPATIBILITY_NONE);
FreeTypeGX *fontSystem[50];
void InitFreeType(uint8_t* fontBuffer, FT_Long bufferSize)
{
FT_Init_FreeType(&ftLibrary);
FT_New_Memory_Face(ftLibrary, (FT_Byte *)fontBuffer, bufferSize, 0, &ftFace);
ftSlot = ftFace->glyph;
for(int i=0; i<50; i++)
fontSystem[i] = NULL;
}
/**
* Default destructor for the FreeTypeGX class.
*/
FreeTypeGX::~FreeTypeGX() {
this->unloadFont();
void ChangeFontSize(FT_UInt pixelSize)
{
FT_Set_Pixel_Sizes(ftFace, 0, pixelSize);
}
void ClearFontData()
{
for(int i=0; i<50; i++)
{
if(fontSystem[i])
delete fontSystem[i];
fontSystem[i] = NULL;
}
}
/**
@ -52,23 +62,38 @@ FreeTypeGX::~FreeTypeGX() {
* @param strChar Character string to be converted.
* @return Wide character representation of supplied character string.
*/
wchar_t* FreeTypeGX::charToWideChar(char* strChar) {
wchar_t *strWChar;
strWChar = new wchar_t[strlen(strChar) + 1];
char *tempSrc = strChar;
wchar_t *tempDest = strWChar;
while((*tempDest++ = *tempSrc++));
wchar_t* charToWideChar(const char* strChar)
{
wchar_t *strWChar;
strWChar = new wchar_t[strlen(strChar) + 1];
return strWChar;
char *tempSrc = (char *)strChar;
wchar_t *tempDest = strWChar;
while((*tempDest++ = *tempSrc++));
return strWChar;
}
/**
* Default constructor for the FreeTypeGX class.
*
* \overload
* @param textureFormat Optional format (GX_TF_*) of the texture as defined by the libogc gx.h header file. If not specified default value is GX_TF_RGBA8.
* @param vertexIndex Optional vertex format index (GX_VTXFMT*) of the glyph textures as defined by the libogc gx.h header file. If not specified default value is GX_VTXFMT1.
*/
wchar_t* FreeTypeGX::charToWideChar(const char* strChar) {
return FreeTypeGX::charToWideChar((char*) strChar);
FreeTypeGX::FreeTypeGX(FT_UInt pixelSize, uint8_t textureFormat, uint8_t vertexIndex) {
this->textureFormat = textureFormat;
this->setVertexFormat(vertexIndex);
this->setCompatibilityMode(FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR | FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE);
this->ftPointSize = pixelSize;
this->ftKerningEnabled = FT_HAS_KERNING(ftFace);
}
/**
* Default destructor for the FreeTypeGX class.
*/
FreeTypeGX::~FreeTypeGX() {
this->unloadFont();
}
/**
@ -149,43 +174,6 @@ void FreeTypeGX::setDefaultMode() {
}
}
/**
* Loads and processes a specified true type font buffer to a specific point size.
*
* This routine takes a precompiled true type font buffer and loads the necessary processed data into memory. This routine should be called before drawText will succeed.
*
* @param fontBuffer A pointer in memory to a precompiled true type font buffer.
* @param bufferSize Size of the true type font buffer in bytes.
* @param pointSize The desired point size this wrapper's configured font face.
* @param cacheAll Optional flag to specify if all font characters should be cached when the class object is created. If specified as false the characters only become cached the first time they are used. If not specified default value is false.
*/
uint16_t FreeTypeGX::loadFont(uint8_t* fontBuffer, FT_Long bufferSize, FT_UInt pointSize, bool cacheAll) {
this->unloadFont();
this->ftPointSize = pointSize;
FT_New_Memory_Face(this->ftLibrary, (FT_Byte *)fontBuffer, bufferSize, 0, &this->ftFace);
if(this->ftPointSize > 0)
FT_Set_Pixel_Sizes(this->ftFace, 0, this->ftPointSize);
this->ftSlot = this->ftFace->glyph;
this->ftKerningEnabled = FT_HAS_KERNING(this->ftFace);
if (cacheAll) {
return this->cacheGlyphDataComplete();
}
return 0;
}
/**
*
* \overload
*/
uint16_t FreeTypeGX::loadFont(const uint8_t* fontBuffer, FT_Long bufferSize, FT_UInt pointSize, bool cacheAll) {
return this->loadFont((uint8_t *)fontBuffer, bufferSize, pointSize, cacheAll);
}
/**
* Clears all loaded font glyph data.
*
@ -195,9 +183,6 @@ void FreeTypeGX::unloadFont() {
if(this->fontData.size() == 0)
return;
GX_DrawDone();
GX_Flush();
for( std::map<wchar_t, ftgxCharData>::iterator i = this->fontData.begin(); i != this->fontData.end(); i++) {
free(i->second.glyphDataTexture);
}
@ -205,12 +190,6 @@ void FreeTypeGX::unloadFont() {
this->fontData.clear();
}
void FreeTypeGX::changeSize(FT_UInt pointSize) {
this->unloadFont();
this->ftPointSize = pointSize;
FT_Set_Pixel_Sizes(this->ftFace, 0, this->ftPointSize);
}
/**
* Adjusts the texture data buffer to necessary width for a given texture format.
*
@ -286,24 +265,24 @@ ftgxCharData *FreeTypeGX::cacheGlyphData(wchar_t charCode) {
FT_UInt gIndex;
uint16_t textureWidth = 0, textureHeight = 0;
gIndex = FT_Get_Char_Index( this->ftFace, charCode );
if (!FT_Load_Glyph(this->ftFace, gIndex, FT_LOAD_DEFAULT )) {
FT_Render_Glyph( this->ftSlot, FT_RENDER_MODE_NORMAL );
gIndex = FT_Get_Char_Index( ftFace, charCode );
if (!FT_Load_Glyph(ftFace, gIndex, FT_LOAD_DEFAULT )) {
FT_Render_Glyph( ftSlot, FT_RENDER_MODE_NORMAL );
if(this->ftSlot->format == FT_GLYPH_FORMAT_BITMAP) {
FT_Bitmap *glyphBitmap = &this->ftSlot->bitmap;
if(ftSlot->format == FT_GLYPH_FORMAT_BITMAP) {
FT_Bitmap *glyphBitmap = &ftSlot->bitmap;
textureWidth = adjustTextureWidth(glyphBitmap->width, this->textureFormat);
textureHeight = adjustTextureHeight(glyphBitmap->rows, this->textureFormat);
this->fontData[charCode] = (ftgxCharData){
this->ftSlot->advance.x >> 6,
ftSlot->advance.x >> 6,
gIndex,
textureWidth,
textureHeight,
this->ftSlot->bitmap_top,
this->ftSlot->bitmap_top,
textureHeight - this->ftSlot->bitmap_top,
ftSlot->bitmap_top,
ftSlot->bitmap_top,
textureHeight - ftSlot->bitmap_top,
NULL
};
this->loadGlyphData(glyphBitmap, &this->fontData[charCode]);
@ -324,14 +303,14 @@ ftgxCharData *FreeTypeGX::cacheGlyphData(wchar_t charCode) {
uint16_t FreeTypeGX::cacheGlyphDataComplete() {
uint16_t i = 0;
FT_UInt gIndex;
FT_ULong charCode = FT_Get_First_Char( this->ftFace, &gIndex );
FT_ULong charCode = FT_Get_First_Char( ftFace, &gIndex );
while ( gIndex != 0 ) {
if(this->cacheGlyphData(charCode) != NULL) {
i++;
}
charCode = FT_Get_Next_Char( this->ftFace, charCode, &gIndex );
charCode = FT_Get_Next_Char( ftFace, charCode, &gIndex );
}
return i;
@ -471,7 +450,7 @@ uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t *text, GXColor color
if(glyphData != NULL) {
if(this->ftKerningEnabled && i) {
FT_Get_Kerning( this->ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta );
FT_Get_Kerning( ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta );
x_pos += pairDelta.x >> 6;
}
@ -561,7 +540,7 @@ uint16_t FreeTypeGX::getWidth(wchar_t *text) {
if(glyphData != NULL) {
if(this->ftKerningEnabled && (i > 0)) {
FT_Get_Kerning( this->ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta );
FT_Get_Kerning( ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta );
strWidth += pairDelta.x >> 6;
}

View File

@ -220,6 +220,11 @@ typedef struct ftgxDataOffset_ {
const GXColor ftgxWhite = (GXColor){0xff, 0xff, 0xff, 0xff}; /**< Constant color value used only to sanitize Doxygen documentation. */
void InitFreeType(uint8_t* fontBuffer, FT_Long bufferSize);
void ChangeFontSize(FT_UInt pixelSize);
wchar_t* charToWideChar(const char* p);
void ClearFontData();
/*! \class FreeTypeGX
* \brief Wrapper class for the libFreeType library with GX rendering.
* \author Armin Tamzarian
@ -232,9 +237,6 @@ const GXColor ftgxWhite = (GXColor){0xff, 0xff, 0xff, 0xff}; /**< Constant color
class FreeTypeGX {
private:
FT_Library ftLibrary; /**< FreeType FT_Library instance. */
FT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */
FT_GlyphSlot ftSlot; /**< FreeType reusable FT_GlyphSlot glyph container object. */
FT_UInt ftPointSize; /**< Requested size of the rendered font. */
bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */
@ -261,18 +263,12 @@ class FreeTypeGX {
void copyFeatureToFramebuffer(f32 featureWidth, f32 featureHeight, int16_t screenX, int16_t screenY, GXColor color);
public:
FreeTypeGX(uint8_t textureFormat = GX_TF_RGBA8, uint8_t vertexIndex = GX_VTXFMT1);
FreeTypeGX(FT_UInt pixelSize, uint8_t textureFormat = GX_TF_RGBA8, uint8_t vertexIndex = GX_VTXFMT1);
~FreeTypeGX();
static wchar_t* charToWideChar(char* p);
static wchar_t* charToWideChar(const char* p);
void setVertexFormat(uint8_t vertexIndex);
void setCompatibilityMode(uint32_t compatibilityMode);
uint16_t loadFont(uint8_t* fontBuffer, FT_Long bufferSize, FT_UInt pointSize, bool cacheAll = false);
uint16_t loadFont(const uint8_t* fontBuffer, FT_Long bufferSize, FT_UInt pointSize, bool cacheAll = false);
void changeSize(FT_UInt pointSize);
uint16_t drawText(int16_t x, int16_t y, wchar_t *text, GXColor color = ftgxWhite, uint16_t textStyling = FTGX_NULL);
uint16_t drawText(int16_t x, int16_t y, wchar_t const *text, GXColor color = ftgxWhite, uint16_t textStyling = FTGX_NULL);

View File

@ -60,7 +60,6 @@ int ResetRequested = 0;
int ExitRequested = 0;
char appPath[1024];
int appLoadMethod = METHOD_AUTO;
FreeTypeGX *fontSystem;
int frameskip = 0;
unsigned char * nesrom = NULL;
@ -267,9 +266,7 @@ int main(int argc, char *argv[])
InitialiseAudio();
// Initialize font system
fontSystem = new FreeTypeGX();
fontSystem->loadFont(font_ttf, font_ttf_size, 0);
fontSystem->setCompatibilityMode(FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR | FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE);
InitFreeType((u8*)font_ttf, font_ttf_size);
InitGUIThreads();

View File

@ -12,6 +12,8 @@
#ifndef _FCEUGX_H_
#define _FCEUGX_H_
#include <unistd.h>
#define APPNAME "FCE Ultra GX"
#define APPVERSION "3.0.5"
#define PREF_FILE_NAME "settings.xml"

View File

@ -50,7 +50,7 @@
#include "pad.h"
#include "oggplayer.h"
extern FreeTypeGX *fontSystem;
extern FreeTypeGX *fontSystem[];
#define SCROLL_INITIAL_DELAY 20
#define SCROLL_LOOP_DELAY 3

View File

@ -46,7 +46,7 @@ GuiText::GuiText(const char * t, int s, GXColor c)
if(t)
{
origText = strdup(t);
text = fontSystem->charToWideChar((char *)t);
text = charToWideChar(t);
}
}
@ -75,7 +75,7 @@ GuiText::GuiText(const char * t)
if(t)
{
origText = strdup(t);
text = fontSystem->charToWideChar((char *)t);
text = charToWideChar(t);
}
}
@ -110,7 +110,7 @@ void GuiText::SetText(const char * t)
if(t)
{
origText = strdup(t);
text = fontSystem->charToWideChar((char *)t);
text = charToWideChar(t);
}
}
@ -218,7 +218,9 @@ void GuiText::Draw()
if(newSize != currentSize)
{
fontSystem->changeSize(newSize);
ChangeFontSize(newSize);
if(!fontSystem[newSize])
fontSystem[newSize] = new FreeTypeGX(newSize);
currentSize = newSize;
}
@ -236,7 +238,7 @@ void GuiText::Draw()
{
if(strlen(tmpText) > maxChar)
tmpText[maxChar] = 0;
textDyn = fontSystem->charToWideChar(tmpText);
textDyn = charToWideChar(tmpText);
}
if(textScroll == SCROLL_HORIZONTAL)
@ -270,11 +272,11 @@ void GuiText::Draw()
strncat(&tmpText[dynlen+2], origText, maxChar - dynlen - 2);
}
if(textDyn) delete textDyn;
textDyn = fontSystem->charToWideChar(tmpText);
textDyn = charToWideChar(tmpText);
}
}
if(textDyn)
fontSystem->drawText(this->GetLeft(), this->GetTop()+voffset, textDyn, c, style);
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop()+voffset, textDyn, c, style);
}
else if(wrap)
{
@ -328,19 +330,19 @@ void GuiText::Draw()
for(i=0; i < linenum; i++)
{
fontSystem->drawText(this->GetLeft(), this->GetTop()+voffset+i*lineheight, textrow[i], c, style);
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop()+voffset+i*lineheight, textrow[i], c, style);
delete textrow[i];
}
}
else
{
fontSystem->drawText(this->GetLeft(), this->GetTop()+voffset, textDyn, c, style);
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop()+voffset, textDyn, c, style);
}
free(tmpText);
}
else
{
fontSystem->drawText(this->GetLeft(), this->GetTop()+voffset, text, c, style);
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop()+voffset, text, c, style);
}
this->UpdateEffects();
}