mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-11-24 11:39:21 +01:00
fix performance problems with using multiple font sizes
This commit is contained in:
parent
ae13bd130e
commit
d5e43d1048
@ -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,11 +62,13 @@ 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* charToWideChar(const char* strChar)
|
||||
{
|
||||
wchar_t *strWChar;
|
||||
strWChar = new wchar_t[strlen(strChar) + 1];
|
||||
|
||||
char *tempSrc = strChar;
|
||||
char *tempSrc = (char *)strChar;
|
||||
wchar_t *tempDest = strWChar;
|
||||
while((*tempDest++ = *tempSrc++));
|
||||
|
||||
@ -64,11 +76,24 @@ wchar_t* FreeTypeGX::charToWideChar(char* strChar) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -50,7 +50,7 @@
|
||||
#include "input.h"
|
||||
#include "oggplayer.h"
|
||||
|
||||
extern FreeTypeGX *fontSystem;
|
||||
extern FreeTypeGX *fontSystem[];
|
||||
|
||||
#define SCROLL_INITIAL_DELAY 20
|
||||
#define SCROLL_LOOP_DELAY 3
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -64,7 +64,6 @@ int ResetRequested = 0;
|
||||
int ExitRequested = 0;
|
||||
char appPath[1024];
|
||||
int appLoadMethod = METHOD_AUTO;
|
||||
FreeTypeGX *fontSystem;
|
||||
|
||||
/****************************************************************************
|
||||
* Shutdown / Reboot / Exit
|
||||
@ -438,9 +437,7 @@ main(int argc, char *argv[])
|
||||
S9xInitSync(); // initialize frame sync
|
||||
|
||||
// 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();
|
||||
|
||||
|
@ -100,6 +100,6 @@ extern int ShutdownRequested;
|
||||
extern int ExitRequested;
|
||||
extern char appPath[];
|
||||
extern int appLoadMethod;
|
||||
extern FreeTypeGX *fontSystem;
|
||||
extern FreeTypeGX *fontSystem[];
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user