Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

799 lines
22 KiB

//===== Copyright (c) Valve Corporation, All rights reserved. ======//
//
// Purpose: PS3-specific font code that for historical reasons is hidden
// in the materialsystem.
//
//==================================================================//
#include "pch_materialsystem.h"
#ifndef _PS3
#define MATSYS_INTERNAL
#endif
#include "cmaterialsystem.h"
#include "colorspace.h"
#include "materialsystem/materialsystem_config.h"
#include "materialsystem/imaterialproxyfactory.h"
#include "IHardwareConfigInternal.h"
#include "shadersystem.h"
#include "texturemanager.h"
#include "shaderlib/ShaderDLL.h"
#include "tier1/callqueue.h"
#include "vstdlib/jobthread.h"
#include "cmatnullrendercontext.h"
#include "datacache/iresourceaccesscontrol.h"
#include "filesystem/IQueuedLoader.h"
#include "filesystem/IXboxInstaller.h"
#include "cdll_int.h"
#include <cell/sysmodule.h>
#include <cell/font.h>
#include <cell/fontft.h>
#include "../common/vgui_surfacelib/vguifont.h"
#ifdef _PS3
#include "ps3_pathinfo.h"
#endif
// NOTE: This must be the last file included!!!
#include "tier0/memdbgon.h"
static const CellFontLibrary *Fontlib();
// in case I make HPS3FONT something other than just a pointer
static inline CellFont *CellFontFromHandle( HPS3FONT &h )
{
return (CellFont *)h;
}
wchar_t g_wchFallbackGlyph = L'_';
static inline bool ShouldFallBackToSystemFontForWChar( wchar_t wch, int &nFontTallAdjustment )
{
if ( ( wch == 0x00AE /*(R)*/ ) || ( wch == 0x2122 /*(TM)*/ ) )
{
nFontTallAdjustment = 1;
return true;
}
return false;
}
#define TEXTURE_PAGE_HEIGHT 128 // copied from FontTextureCache.cpp, which for some reason hardcodes this. because there's multiple implementations
// of the font cache strewn throughout various libraries all linked into the vgui dll, I didn't feel safe changing
// it to just use larger textures.
class CFallbackFont: public CellFont
{
protected:
int m_nInitError;
int m_nTall;
CellFontHorizontalLayout m_hlayout;
public:
CFallbackFont(): m_nInitError(-1), m_nTall( -1 )
{
}
void Init()
{
if( m_nInitError == CELL_OK )
{
// already initialized
return ;
}
CellFontType fontType;
fontType.type = CELL_FONT_TYPE_GOTHIC_JAPANESE_CJK_LATIN_SET;
fontType.map = CELL_FONT_MAP_UNICODE;
m_nInitError = cellFontOpenFontset( Fontlib(), &fontType, this );
if( m_nInitError == CELL_OK )
{
Warning("Cannot open fallback font, error 0x%X\n", m_nInitError );
}
}
CellFontHorizontalLayout *GetHorizontalLayout()
{
return &m_hlayout;
}
int SetTall( int nTall )
{
if( m_nInitError != CELL_OK )
{
return m_nInitError;
}
if( nTall == m_nTall )
{
return CELL_OK;
}
float pointSize = nTall * 0.79f;
cellFontSetScalePixel( this, pointSize, pointSize );
// sometimes we ask for bigger fonts than the packer can handle. Also, because of accents etc, the font may poke out of the requested tall value.
// The packer is for some reason hardcoded to a maximum height of 128.
cellFontGetHorizontalLayout( this, &m_hlayout );
if ( m_hlayout.lineHeight + m_hlayout.effectHeight > TEXTURE_PAGE_HEIGHT )
{
Warning("FAILSAFE: Fallback Font at '%d' tall is actually %d pixels high, but max texture page is %d. Shrinking to ",
nTall, (int)(m_hlayout.lineHeight + m_hlayout.effectHeight), TEXTURE_PAGE_HEIGHT );
do
{
pointSize *= 0.9;
cellFontSetScalePixel( this, nTall, nTall );
cellFontGetHorizontalLayout( this, &m_hlayout );
}
while ( ( m_hlayout.lineHeight + m_hlayout.effectHeight > TEXTURE_PAGE_HEIGHT ) && ( pointSize >= 1 ) );
Warning( "%.2f\n", pointSize );
}
m_nTall = nTall;
return CELL_OK;
}
void Shutdown()
{
if( m_nInitError == CELL_OK )
{
int nError = cellFontCloseFont( this );
if( nError != CELL_OK )
{
Warning("Cannot close fallback font, error 0x%X\n", nError );
}
}
}
};
CFallbackFont g_fallbackFont;
void CMaterialSystem::InitializePS3Fonts()
{
m_vExtantFonts.EnsureCapacity(8);
}
class CTempFontHandle
{
public:
CMaterialSystem * m_pMaterialSystem;
MaterialLock_t m_hLock;
CellFont * m_pNewFont;
public:
CTempFontHandle( CMaterialSystem * pMaterialSystem):
m_pMaterialSystem( pMaterialSystem )
{
m_hLock = pMaterialSystem->Lock();
m_pNewFont = new CellFont;
}
CellFont* DetachFont()
{
CellFont * pFont = m_pNewFont;
m_pNewFont = NULL;
return pFont;
}
~CTempFontHandle()
{
if( m_pNewFont )
{
delete m_pNewFont;
}
m_pMaterialSystem->Unlock( m_hLock );
}
};
HPS3FONT CMaterialSystem::OpenTrueTypeFont( const char *pFontname, int tall, int style )
{
CTempFontHandle hTemp( this );
static int sUniquePositiveNumber = 0;
// need absolute disk path, look in resource then platform
char fontpath[MAX_PATH] = {0};
struct fontTable_t
{
const char *pFontName;
const char *pPath;
bool m_bRestrictiveLoadIntoMemory;
bool m_bAlwaysLoadIntoMemory;
};
int nCellError;
if( !V_stricmp( pFontname, "system" ) )
{
CellFontType fontType;
fontType.type = CELL_FONT_TYPE_GOTHIC_JAPANESE_CJK_LATIN_SET;
fontType.map = CELL_FONT_MAP_UNICODE;
nCellError = cellFontOpenFontset( Fontlib(), &fontType, hTemp.m_pNewFont );
}
else if( !V_stricmp( pFontname, "japanese cjk latin" ) )
{
CellFontType fontType;
fontType.type = CELL_FONT_TYPE_GOTHIC_JAPANESE_CJK_LATIN_SET;
fontType.map = CELL_FONT_MAP_UNICODE;
nCellError = cellFontOpenFontset( Fontlib(), &fontType, hTemp.m_pNewFont );
}
else
{
// explicit mapping required, dvd searching too expensive
static fontTable_t fontToFilename[] =
{
#include "shaderapidx9/fontremaptable.h"
};
// remap typeface to diskname
char const *pDiskname = NULL;
for ( int i=0; i<ARRAYSIZE( fontToFilename ); i++ )
{
if ( !V_stricmp( pFontname, fontToFilename[i].pFontName ) )
{
pDiskname = fontToFilename[i].pPath;
break;
}
}
if ( !pDiskname )
{
// not found
DevWarning( "PS3: True Type Font: '%s' unknown.\n", pFontname );
}
else
{
Q_snprintf( fontpath, ARRAYSIZE( fontpath ), "%s/%s", g_pPS3PathInfo->GameImagePath(), pDiskname );
}
// if we failed to find the font, substitute a system font
if ( fontpath[0] == 0 )
{
CellFontType fontType;
fontType.type = CELL_FONT_TYPE_GOTHIC_JAPANESE_CJK_LATIN_SET;
fontType.map = CELL_FONT_MAP_UNICODE;
nCellError = cellFontOpenFontset( Fontlib(), &fontType, hTemp.m_pNewFont );
}
else
{
nCellError = cellFontOpenFontFile(
Fontlib(),
reinterpret_cast<uint8_t *>(fontpath),
0,
++sUniquePositiveNumber,
hTemp.m_pNewFont );
}
}
CellFont *pNewFont = NULL;
if ( nCellError != CELL_FONT_OK )
{
Warning( "could not open font '%s': %x\n", pFontname, nCellError );
return false;
}
else
{
pNewFont = hTemp.DetachFont(); // do not release the font structure
m_vExtantFonts.AddToTail( pNewFont );
}
float pointSize = tall * 0.79f;
cellFontSetScalePixel( pNewFont, pointSize, pointSize );
// sometimes we ask for bigger fonts than the packer can handle. Also, because of accents etc, the font may poke out of the requested tall value.
// The packer is for some reason hardcoded to a maximum height of 128.
CellFontHorizontalLayout hlayout;
cellFontGetHorizontalLayout( pNewFont, &hlayout );
if ( hlayout.lineHeight + hlayout.effectHeight > TEXTURE_PAGE_HEIGHT )
{
Warning("FAILSAFE: %s at '%d' tall is actually %d pixels high, but max texture page is %d. Shrinking to ",
pFontname, tall, (int)(hlayout.lineHeight + hlayout.effectHeight), TEXTURE_PAGE_HEIGHT );
do
{
pointSize *= 0.9;
cellFontSetScalePixel( pNewFont, tall, tall );
cellFontGetHorizontalLayout( pNewFont, &hlayout );
}
while ( ( hlayout.lineHeight + hlayout.effectHeight > TEXTURE_PAGE_HEIGHT ) && (pointSize >= 1) );
Warning( "%.2f\n", pointSize );
}
/*
nCellError = cellFontGetHorizontalLayout( &m_sFont, &m_HorizontalLayout );
AssertMsg2( nCellError == CELL_OK, "Could not get horizontal layout for font %s (%x)\n", m_szName.String(), nCellError );
*/
/*
nCellError = cellFontGetVerticalLayout( &m_sFont, &m_VerticalLayout );
AssertMsg2( nCellError == CELL_OK, "Could not get vertical layout for font %s (%x)\n", m_szName.String(), nCellError );
*/
return pNewFont;
}
void CMaterialSystem::CloseTrueTypeFont( HPS3FONT hFont )
{
MaterialLock_t hLock = Lock();
// find the font in the vector
CellFont *pFont = CellFontFromHandle( hFont );
cellFontCloseFont( pFont );
if ( m_vExtantFonts.FindAndFastRemove( pFont ) )
{
delete pFont;
}
else
{
AssertMsg1( false, "Tried to remove a font %x which wasn't in the material system's library\n", hFont );
}
Unlock( hLock );
}
bool CMaterialSystem::GetTrueTypeFontMetrics( HPS3FONT hFont, int nFallbackTall, wchar_t wchFirst, wchar_t wchLast, CPS3FontMetrics * RESTRICT pFontMetrics, CPS3CharMetrics * RESTRICT pCharMetrics )
{
MaterialLock_t hLock = Lock();
int numChars = wchLast - wchFirst + 1;
V_memset( pCharMetrics, 0, numChars * sizeof( CPS3CharMetrics ) );
CellFont * RESTRICT pFont = CellFontFromHandle( hFont );
int nCellError = cellFontGetHorizontalLayout( pFont, pFontMetrics );
AssertMsg1( nCellError == CELL_OK, "Could not get horizontal layout for font (%x)\n", nCellError );
// we will still need to go and fill in the max width once we've got the data for all the characters
float fMaxWidth = 0;
for ( int i = 0; i < numChars; i++ )
{
int nMetricsError = CELL_FONT_ERROR_FATAL;
int nFallbackFontTallAdjustment = 0;
if ( !ShouldFallBackToSystemFontForWChar( wchFirst + i, nFallbackFontTallAdjustment ) )
{
nMetricsError = cellFontGetCharGlyphMetrics( pFont, wchFirst + i, pCharMetrics + i );
}
if( nMetricsError != CELL_OK )
{
// try the fallback font
int nFallbackError = g_fallbackFont.SetTall( nFallbackTall + nFallbackFontTallAdjustment );
if( nFallbackError == CELL_OK )
{
nMetricsError = cellFontGetCharGlyphMetrics( &g_fallbackFont, wchFirst + i, pCharMetrics + i );
}
}
if( nMetricsError != CELL_OK )
{
nMetricsError = cellFontGetCharGlyphMetrics( pFont, g_wchFallbackGlyph, pCharMetrics + i );
}
if ( nMetricsError == CELL_OK )
{
fMaxWidth = fmax( fMaxWidth, pCharMetrics[i].Horizontal.advance + 1 );
}
else
{
memset( pCharMetrics+i, 0, sizeof(*pCharMetrics) );
}
}
pFontMetrics->fMaxWidth = fMaxWidth;
Unlock( hLock );
return nCellError == CELL_OK;
}
// encapsulates the ps3 fontlib renderer class with a RAII interface
// so it binds/unbinds automatically
class CFontRendererRAII
{
public:
CFontRendererRAII( CellFont *pBoundFont );
~CFontRendererRAII();
bool IsValid() { return m_nInitSuccess == CELL_FONT_OK; }
protected:
CellFontRenderer m_Renderer;
CellFont *m_pFont;
int m_nInitSuccess;
};
CFontRendererRAII::CFontRendererRAII( CellFont *pBoundFont ) : m_pFont(NULL)
{
CellFontRendererConfig config;
CellFontRendererConfig_initialize( &config );
// proper setup here
m_nInitSuccess = cellFontCreateRenderer( Fontlib(), &config, &m_Renderer );
if ( m_nInitSuccess != CELL_FONT_OK )
{
return ; // we have failed. we are failures. the stench of failure hangs upon us.
}
// connect the renderer to the font
m_nInitSuccess = cellFontBindRenderer( pBoundFont, &m_Renderer );
if ( m_nInitSuccess != CELL_FONT_OK )
{
return ; // we have failed. we are failures. the stench of failure hangs upon us.
}
m_pFont = pBoundFont;
}
CFontRendererRAII::~CFontRendererRAII()
{
if ( m_pFont )
{
cellFontUnbindRenderer( m_pFont );
}
cellFontDestroyRenderer( &m_Renderer );
}
// OPTIMIZATION OPPORTUNITY:
// This can be made to run on the RSX instead of the PPU, if necessary.
bool CMaterialSystem::GetTrueTypeGlyphs( HPS3FONT hFont, int nFallbackTall, int numChars, wchar_t *pWch, int *pOffsetX, int *pOffsetY, int * RESTRICT pWidth, int * RESTRICT pHeight, unsigned char *pRGBA, int *pRGBAOffset )
{
VPROF( "CMaterialSystem::GetTrueTypeGlyphs" );
MaterialLock_t hLock = Lock();
// Figure out the size of surface/texture we need to allocate
int rtWidth = 0;
int rtHeight = 0;
for ( int i = 0; i < numChars; i++ )
{
//rtWidth += pWidth[i];
rtWidth = MAX( rtWidth, pWidth[i] );
rtHeight = MAX( rtHeight, pHeight[i] );
}
/*
// per resolve() restrictions
rtWidth = AlignValue( rtWidth, 32 );
rtHeight = AlignValue( rtHeight, 32 );
*/
if ( rtWidth == 0 || rtHeight == 0 )
{
AssertMsg2( false, "Tried to draw a %dx%d glyph! What are you trying to pull?!\n", rtWidth, rtHeight );
Unlock( hLock );
return false;
}
CellFont *pFont = CellFontFromHandle( hFont );
CFontRendererRAII renderer( pFont ), *pFallbackRenderer = NULL;
CellFontRenderSurface surface;
CellFontGlyphMetrics metrics;
CellFontImageTransInfo transInfo;
CellFontHorizontalLayout hlayoutSlowWeShouldMoveThisIntoTheFontClass;
cellFontRenderSurfaceInit( &surface, NULL, rtWidth, 1, rtWidth, rtHeight ); // the surface doesn't actually use the memory pointer (go figure)
cellFontRenderSurfaceSetScissor( &surface, 0, 0, rtWidth, rtHeight );
cellFontGetHorizontalLayout( pFont, &hlayoutSlowWeShouldMoveThisIntoTheFontClass );
const int baselineY = floor(hlayoutSlowWeShouldMoveThisIntoTheFontClass.baseLineY);
// struct XUIRect { int x, int y, int w, int h };
// Draw the characters, stepping across the texture
// int xCursor = 0;
unsigned int successfulWrites = 0;
for ( int i = 0; i < numChars; i++)
{
/*
// FIXME: the drawRect params don't make much sense (should use "(xCursor+pWidth[i]), pHeight[i]", but then some characters disappear!)
XUIRect drawRect = XUIRect( xCursor + pOffsetX[i], pOffsetY[i], rtWidth, rtHeight );
cellFontRenderSurfaceSetScissor( &surface, drawRect.x, drawRect.y, drawRect.w, drawRect.h );
wchar_t text[2] = { pWch[i], 0 };
XuiDrawText( m_hDC, text, XUI_FONT_STYLE_NORMAL|XUI_FONT_STYLE_SINGLE_LINE|XUI_FONT_STYLE_NO_WORDWRAP, 0, &drawRect );
xCursor += pWidth[i];
*/
// draw one glyph to the surface
int ps3suc = CELL_FONT_ERROR_FATAL;
int nFallbackFontTallAdjustment = 0;
if ( !ShouldFallBackToSystemFontForWChar( pWch[i], nFallbackFontTallAdjustment ) )
{
ps3suc = cellFontRenderCharGlyphImage( pFont, pWch[i], &surface, 0, 0, &metrics, &transInfo );
}
if ( ps3suc != CELL_OK )
{
if( CELL_OK == g_fallbackFont.SetTall( nFallbackTall + nFallbackFontTallAdjustment ) )
{
if( !pFallbackRenderer )
pFallbackRenderer = new CFontRendererRAII( &g_fallbackFont );
ps3suc = cellFontRenderCharGlyphImage( &g_fallbackFont, pWch[i], &surface, 0, 0, &metrics, &transInfo );
}
}
if( ps3suc != CELL_OK )
{
ps3suc = cellFontRenderCharGlyphImage( pFont, g_wchFallbackGlyph, &surface, 0, 0, &metrics, &transInfo );
}
if ( ps3suc == CELL_OK )
{
// blit the glyph to the bitmap
const int ibw = transInfo.imageWidthByte;
const int iBearingY = ceilf(metrics.Horizontal.bearingY); // start the conversion early to avoid a LHS
int destPitch = pWidth[i]*4; // distance between one row and the next IN BYTES
unsigned char *pLinear = pRGBA + pRGBAOffset[i];
// Clear out all pixels to black, since the source glyph size may not match the destination buffer size perfectly
memset( pLinear, 0, pHeight[i] * destPitch );
if ( transInfo.imageHeight==0 || transInfo.imageWidth==0 )
{
// this can happen for space or control characters
// just blank out the destination box
continue; // bail out and go to next character !
}
// work out the size of the region to copy -- which is the smaller of the source or destination buffer.
// in theory these two should be identical, but the PS3 OS tends to overallocate space slightly
// in its render surface, and sometimes the VGUI font code is expecting a blank column of pixels
// where the PS3 generates none.
// also we'll try to align the font glyph to the bottom of the destination rect, rather than
// the top.
int numLeftPadPixels = ( int )floorf( metrics.Horizontal.bearingX );
numLeftPadPixels = MAX( 0, numLeftPadPixels );
int iteratorMaxColumn = MIN( pWidth[i] - numLeftPadPixels, transInfo.imageWidth );
int iteratorMaxRow = MIN( pHeight[i], transInfo.imageHeight );
unsigned char *pLinearAligned = pLinear; // work out where to start writing into the image so that chars are aligned to bottom of rect
pLinearAligned = pLinear + MAX(0, baselineY-iBearingY)*destPitch;
// for ( int row = 0 ; row < transInfo.imageHeight ; ++row )
for ( int row = 0 ; row < iteratorMaxRow; ++row )
{
uint32 * pRowStart = reinterpret_cast<uint32 *>(pLinearAligned + (row*destPitch)); // we will write the RGBA one word at a time
for ( int col = 0 ; col < iteratorMaxColumn; ++col )
{
// white characters; only the alpha mask is copied from the rendered glyph
// exception: totally absent regions are marked as just black
uint8 a = transInfo.Image[ row * ibw + col ];
*(pRowStart + col + numLeftPadPixels) = a ? 0xFFFFFF00 | a : 0 ;
}
}
#if 0
if ( FILE *f = fopen( "/app_home/dbgfonts.txt", "a+" ) )
{
fprintf( f, "% 4d %C [%dx%d]\n",
pWch[i], pWch[i],
transInfo.imageWidth, transInfo.imageHeight
);
fprintf( f, " [%d]\n",
pWidth[i]
);
fprintf( f, " %0.5f %0.5f %0.5f\n",
metrics.Horizontal.bearingX, metrics.width, metrics.Horizontal.advance
);
for ( int row = 0; row < MAX( MAX( pHeight[i], ceilf( metrics.height ) ), transInfo.imageHeight ); ++ row )
{
for ( int col = 0; col < MAX( pWidth[i], ceilf( metrics.Horizontal.advance ) ); ++ col )
{
uint8 a = transInfo.Image[ row * ibw + col ];
fprintf( f, a ? ( (a>0x20) ? "X" : "*" ) : " " );
}
fprintf( f, "|\n" );
}
fprintf( f, "-----------------------------\n" );
fclose(f);
}
#endif
#if 0 // draw a line around the outer border for debugging
for ( int row = 0 ; row < pHeight[i]; ++row )
{
*(reinterpret_cast<uint32 *>(pLinear + (row*destPitch))+0) = 0xFFFFFFFF;
*(reinterpret_cast<uint32 *>(pLinear + (row*destPitch))+pWidth[i]-1) = 0xFFFFFFFF;
}
// top and bottom row
memset( pLinear, 0xFF, pWidth[i] * 4 );
memset( (pLinear + ((pHeight[i]-1)*destPitch)), 0xFF, pWidth[i] * 4 );
#endif
successfulWrites++;
}
else
{
AssertMsg2( false, "Couldn't draw u'%x', err %x\n", (unsigned int) *(pWch+i), ps3suc );
}
}
if( pFallbackRenderer )
delete pFallbackRenderer;
Unlock( hLock );
return successfulWrites > 0;
}
static int load_libfont_module()
{
int ret;
ret = cellSysmoduleLoadModule( CELL_SYSMODULE_FONT );
if ( ret == CELL_OK ) {
ret = cellSysmoduleLoadModule( CELL_SYSMODULE_FREETYPE_TT );
if ( ret == CELL_OK ) {
ret = cellSysmoduleLoadModule( CELL_SYSMODULE_FONTFT );
if ( ret == CELL_OK ) {
return CELL_OK; // Success
}
// Error handling as follows (Unload all loads)
cellSysmoduleUnloadModule( CELL_SYSMODULE_FREETYPE_TT );
}
cellSysmoduleUnloadModule( CELL_SYSMODULE_FONT );
}
return ret; // Error end
}
static void* fonts_malloc( void*obj, uint32_t size )
{
(void)obj;
return malloc( size );
}
static void fonts_free( void*obj, void*p )
{
(void)obj;
free( p );
}
static void* fonts_realloc( void*obj, void* p, uint32_t size )
{
(void)obj;
return realloc( p, size );
}
static void* fonts_calloc( void*obj, uint32_t numb, uint32_t blockSize )
{
(void)obj;
return calloc( numb, blockSize );
}
static int s_FontLibraryRefCount = 0;
static uint32 *s_FontFileCache = NULL;
static const CellFontLibrary *s_FontLibrary = NULL;
static CellFontEntry *s_UserFontEntries = NULL;
bool CMaterialSystem::PS3InitFontLibrary( unsigned fontFileCacheSizeInBytes, unsigned maxNumFonts )
{
if ( s_FontLibraryRefCount > 0 )
{
// don't need to load the font library, just add one to refcount
++s_FontLibraryRefCount;
return true;
}
else if ( s_FontLibraryRefCount < 0 )
{
Error( "Font library refcount is %d!\n", s_FontLibraryRefCount );
}
else
{
++s_FontLibraryRefCount;
}
VPROF("CMaterialSystem::PS3InitFontLibrary");
if ( s_FontFileCache )
{
Warning("Tried to init font library twice without intervening unload\n");
return false;
}
int ret;
if ( (ret=load_libfont_module()) != CELL_OK )
{
Warning("Could not load font library: %x\n", ret);
}
maxNumFonts = maxNumFonts ? maxNumFonts : 1;
if (s_FontFileCache)
{
Assert(false); // wasn't cleaned up?!
delete[] s_FontFileCache;
}
if (s_UserFontEntries)
{
Assert(false); // wasn't cleaned up?!
delete[] s_UserFontEntries;
}
s_FontFileCache = new uint32[fontFileCacheSizeInBytes >> 2];
s_UserFontEntries = new CellFontEntry[maxNumFonts];
CellFontConfig config;
config.FileCache.buffer = s_FontFileCache;
config.FileCache.size = fontFileCacheSizeInBytes;
config.userFontEntrys = s_UserFontEntries;
config.userFontEntryMax = maxNumFonts;
ret = cellFontInit(&config);
if ( ret == CELL_OK )
{
// can override malloc/free here:
CellFontLibraryConfigFT ftConfig;
CellFontLibraryConfigFT_initialize( &ftConfig );
ftConfig.MemoryIF.Object = NULL;
ftConfig.MemoryIF.Malloc = fonts_malloc;
ftConfig.MemoryIF.Free = fonts_free;
ftConfig.MemoryIF.Realloc = fonts_realloc;
ftConfig.MemoryIF.Calloc = fonts_calloc;
ret = cellFontInitLibraryFreeType( &ftConfig, &s_FontLibrary );
if ( ret == CELL_OK )
{
g_fallbackFont.Init( );
return true;
}
else
{
Warning( "cellFontInitLibraryFreeType failed, %x\n", ret );
return false;
}
}
else
{
Warning( "CellFontInit failed, %x\n", ret );
return false;
}
}
void *CMaterialSystem::PS3GetFontLibPtr()
{
return (void*)s_FontLibrary;
}
void CMaterialSystem::PS3DumpFontLibrary()
{
if ( s_FontLibraryRefCount <= 0 )
{
Warning("Font library refcount is %d during unload!\n", s_FontLibraryRefCount);
return;
}
else if ( s_FontLibrary == NULL )
{
Warning("\t!!!FAILSAFE!!!\nPS3 font library refcount %d but was somehow unloaded!\n", s_FontLibraryRefCount);
s_FontLibraryRefCount = 0;
}
else if ( --s_FontLibraryRefCount > 0 )
{ // refcount is still greater than one, don't need to unload
return;
}
// Warning( "Font library was dumped with %d fonts left open.\n", m_vExtantFonts.Count() );
if ( s_FontLibrary )
{
g_fallbackFont.Shutdown();
cellFontEndLibrary( s_FontLibrary );
cellFontEnd();
delete[] s_FontFileCache;
s_FontFileCache = NULL;
// handled by cellFontEndLibrary: // delete s_FontLibrary;
s_FontLibrary = NULL;
delete[] s_UserFontEntries;
s_UserFontEntries = NULL;
cellSysmoduleUnloadModule( CELL_SYSMODULE_FONTFT );
cellSysmoduleUnloadModule( CELL_SYSMODULE_FREETYPE_TT );
cellSysmoduleUnloadModule( CELL_SYSMODULE_FONT );
}
}
static const CellFontLibrary *Fontlib()
{
return s_FontLibrary;
}