通过调用 CWsScreenDevice::GetNearestFontToDesignHeightInTwips( CFont*& aFont, const TFontSpec& aFontSpec ) 获取字体之后,应当用 CWsScreenDevice::ReleaseFont( CFont* aFont ) 将此屏幕设备对字体资源所增加的 referent count 还原。(我猜测是如此,因为按照文档中的描述,字体是保留在内存中,由不同的应用程序所共享,除非这个字体为某一个屏幕设备所排他性地独享;另外,内存作 为一种系统资源,也是以共享的方式使用字体的情形居多。)
所以,我采用如下方式来使用字体:
class MyUiUtils
{
public:
static TTypeface FindTypeface( const TDesC& aTypefaceName );
static TInt FontHeightInTwips( const TInt aHeightInPixels );
static TInt RequestFontFromScreenDevice( CFont*& aFont, const TFontSpec& aFontSpec );
static void ReturnFontToScreenDevice( CFont* aFont );
};
static TInt FontHeightInTwips( const TInt aHeightInPixels );
static TInt RequestFontFromScreenDevice( CFont*& aFont, const TFontSpec& aFontSpec );
static void ReturnFontToScreenDevice( CFont* aFont );
};
TTypeface MyUiUtils::FindTypeface( const TDesC& aTypefaceName )
{
CWsScreenDevice* scrDev = CCoeEnv::Static()->ScreenDevice();
TInt tfCnt( scrDev->NumTypefaces() );
{
CWsScreenDevice* scrDev = CCoeEnv::Static()->ScreenDevice();
TInt tfCnt( scrDev->NumTypefaces() );
TTypeface tf;
TTypefaceSupport tfSupport;
TTypefaceSupport tfSupport;
for ( TInt i = 0; i < tfCnt; i++ )
{
scrDev->TypefaceSupport( tfSupport, i );
{
scrDev->TypefaceSupport( tfSupport, i );
if ( !aTypefaceName.Compare( tfSupport.iTypeface.iName ) )
{
tf = tfSupport.iTypeface;
break;
}
else
{
}
}
{
tf = tfSupport.iTypeface;
break;
}
else
{
}
}
return tf;
}
}
TInt MyUiUtils::FontHeightInTwips( const TInt aHeightInPixels )
{
CWsScreenDevice* scrDev = CCoeEnv::Static()->ScreenDevice();
{
CWsScreenDevice* scrDev = CCoeEnv::Static()->ScreenDevice();
TInt heightInTwips( scrDev->VerticalPixelsToTwips( aHeightInPixels ) );
return heightInTwips;
}
}
TInt MyUiUtils::RequestFontFromScreenDevice( CFont*& aFont, const TFontSpec& aFontSpec )
{
CWsScreenDevice* scrDev = CCoeEnv::Static()->ScreenDevice();
{
CWsScreenDevice* scrDev = CCoeEnv::Static()->ScreenDevice();
TInt error ( scrDev->GetNearestFontToDesignHeightInTwips( aFont, aFontSpec ) );
return error;
}
}
void MyUiUtils::ReturnFontToScreenDevice( CFont* aFont )
{
CWsScreenDevice* scrDev = CCoeEnv::Static()->ScreenDevice();
{
CWsScreenDevice* scrDev = CCoeEnv::Static()->ScreenDevice();
scrDev->ReleaseFont( aFont );
}
}
由此可见,字体的申请和归还应当成对使用。如下,
void CMyClass::ConstructL()
{
RBuf tfName;
tfName.CleanupClosePushL();
tfName.Assign( StringLoader::LoadL( R_MY_TYPEFACE ) );
TTypeface tf;
tfName.CleanupClosePushL();
tfName.Assign( StringLoader::LoadL( R_MY_TYPEFACE ) );
TTypeface tf;
tf = MyUiUtils::FindTypeface( tfName );
if ( !tf.iName.Length() )
{
tf.iName = tfName;
}
else
{
}
{
tf.iName = tfName;
}
else
{
}
TInt heightInTwips( MyUiUtils::FontHeightInTwips( KMmMapDefaultFontHeight ) );
TFontSpec tfs( tf.iName, heightInTwips );
TFontSpec tfs( tf.iName, heightInTwips );
TInt error( MyUiUtils::RequestFontByFontSpec( iFont, tfs ) );
CleanupStack::PopAndDestroy( &tfName );
}
CleanupStack::PopAndDestroy( &tfName );
}
void CMyClass::~CMyClass()
{
if ( iFont )
{
MyUiUtils::ReturnFontToScreenDevice( iFont );
}
else
{
}
}
{
MyUiUtils::ReturnFontToScreenDevice( iFont );
}
else
{
}
}
否则容易出现 CTypefaceStore 14 的 Panic。
但是,如果你是使用系统提供的封装全局方法的话,就不用如此小心。例如,在 S60 中,如果使用 AknUtils
iFont = const_cast<CFont*>( ApacPlain16() ); 或者
iFont = AknLayoutUtils::FontFromId( EAknLogicalFontPrimaryFont ) );
那么 AknUtils 已经帮你完成了字体资源归还的任务,所以你可以粗心一点。